[android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)...

常见的.postDelayed(runnable, time)方法就是常见的延迟处理的方法之一,postDelayed(mRun,time);当想要需要取消的时候,调用removeCallbacks(mRun);即可,就可以取消postDelayed的方法里面的runnable,当然如果里面runnable已经执行了,那就不可能撤回或者中止了。

http://blog.csdn.net/bluewindtalker/article/details/51984300

下面是布局文件

 

以下是测试代码。

final TextView mRemovecallbackTV = (TextView)findViewById(R.id.tv_demo_removecallback_test_onAnimationEnd);

         mRun = new Runnable() {
            @Override
            public void run() {
                if(DirectionMarqueeDemoActivity.this.isFinishing()){
                    BlueLog.e(TAG,"DirectionMarqueeDemoActivity  isFinishing ");
                    mMarqueeAnimationTV.clearAnimation();
                    mRemovecallbackTV.removeCallbacks(mRun);
                }
                BlueLog.e(TAG, "Runnable   " + DirectionMarqueeDemoActivity.this);
                mRemovecallbackTV.postDelayed(this, 3000);
            }
        };

        findViewById(R.id.btn_demo_removecallback_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mRemovecallbackTV.postDelayed(mRun, 3000);
                BlueLog.e(TAG, " postDelayed " );
            }
        });
        findViewById(R.id.btn_demo_removecallback_stop).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mRemovecallbackTV.removeCallbacks(mRun);
                BlueLog.e(TAG, "removeCallbacks ");
            }
        });

其中mRun为Activity的成员变量。


运行的时候我们发现

[android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)..._第1张图片

即使activity 结束了调用了onDestory方法后这里仍然运行,问题在于代码中,先removeCallBacks,再postDelayed,这里加一个return就好,

[android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)..._第2张图片


正确的代码大家就在removeCallBacks加入return即可,下面是logcat的打印

[android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)..._第3张图片


所以如要要循环调用postDelayed的时候,一样要进行判断是否所属的activity已经退出了。将结束方法一定要体现出来



而postDelayed(runnable, time)有view.postDelayed(mRun, time);和new Handler().postDelayed(mRun,time);这两种,

对于view.postDelayed我们通过源码发现

 public boolean postDelayed(Runnable action, long delayMillis) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.postDelayed(action, delayMillis);
        }
        // Assume that post will succeed later
        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
        return true;
    }
return attachInfo.mHandler.postDelayed(action, delayMillis);最后进入了Handler的postDelayed

public final boolean postDelayed(Runnable r, long delayMillis)
    {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }

而ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);进入ViewRootImpl.java中,

static final class RunQueue {
        private final ArrayList mActions = new ArrayList();

        void post(Runnable action) {
            postDelayed(action, 0);
        }

        void postDelayed(Runnable action, long delayMillis) {
            HandlerAction handlerAction = new HandlerAction();
            handlerAction.action = action;
            handlerAction.delay = delayMillis;

            synchronized (mActions) {
                mActions.add(handlerAction);
            }
        }

        void removeCallbacks(Runnable action) {
            final HandlerAction handlerAction = new HandlerAction();
            handlerAction.action = action;

            synchronized (mActions) {
                final ArrayList actions = mActions;

                while (actions.remove(handlerAction)) {
                    // Keep going
                }
            }
        }

        void executeActions(Handler handler) {
            synchronized (mActions) {
                final ArrayList actions = mActions;
                final int count = actions.size();

                for (int i = 0; i < count; i++) {
                    final HandlerAction handlerAction = actions.get(i);
                    handler.postDelayed(handlerAction.action, handlerAction.delay);
                }

                actions.clear();
            }
        }

最后仍然执行了handler.postDelayed(handlerAction.action, handlerAction.delay),所以两个内容是相差无几的。


其中HandlerAction来自于view调用invalidate时,父View传入的。



你可能感兴趣的:([android小知识]removeCallbacks与postDelayed的恩怨史(removeCallbacks所谓的无效, View和Handler 的postDelayed)...)