TimerTask 就像穿破的袜子, 不能重用

来源:互联网 发布:超市存货管理优化 编辑:程序博客网 时间:2024/06/02 20:16

最近使用写了一个定时更新屏幕颜色的 Android程序, 获得了一些经验

设置思路是: 让Timer 调用 view的postInvalidate, 而后在onDraw中更新屏幕

最初我是这样写的程序, 貌似也正常工作


public class CanvasActivity extends Activity {public final String TAG = "CanvasActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new MyView(this));}class MyView extends View {Random mRandom = new Random();Timer timer = new Timer();TimerTask task = new TimerTask() {public void run() {MyView.this.postInvalidate();}};MyView(Context context) {super(context);}@Overrideprotected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);if (visibility == View.VISIBLE) {timer.schedule(task, 1000, 2000);}}@Overridepublic void onDraw(Canvas canvas) {super.onDraw(canvas);int r = (0x00151515 | mRandom.nextInt()) | Color.BLACK;canvas.drawRGB(r, r, r);}}}


但我想Timer一直在工作, 在程序Pause的时候, 应该让它停掉

实验证明

Timer 单独启动一个线程, 即使Activity 没有前台( onPause), 它也工作

在此程序中,  Activity 在Pause的时候, 因为程序不再前台, 调用了view.postInvalidate() , 而 view 的 onDraw不会触发, 尽管如此, 启动timer让系统资源被浪费.


而后把代码改为 (  当然也可以把相关代码放在 onPause, onResume 中实现  )

protected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);if (visibility == View.VISIBLE) {timer = new Timer();timer.schedule(task, 1000, 2000);} else {timer.cancel();timer.purge();}}

运行时居然报错

... IllegalStateException: TimerTask is scheduledalready...


后来我终于明白

TimerTask 就像穿破的袜子, 要扔不能重用

就是每次都要 new TimerTask

    timer.schedule(new MyTask(), 1000, 2000);


把代码改为下面后, 程序正常工作

class MyTask extends TimerTask {public void run() {MyView.this.postInvalidate();}};@Overrideprotected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);if (visibility == View.VISIBLE) {timer = new Timer();timer.schedule(new MyTask(), 1000, 2000);} else {timer.cancel();timer.purge();}}





原创粉丝点击