返回

记一次Handler的使用

Android

前言

在Android中,Handler是一个非常重要的类,它负责消息的发送和处理。我们可以使用Handler来实现各种各样的需求,例如发送延迟消息、移除消息等。

使用Handler发送延迟消息

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 发送一条延迟消息,10秒后执行
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 这里执行你要做的事情
            }
        }, 10000);
    }
}

上面的代码中,我们首先创建一个Handler对象,然后使用postDelayed()方法发送一条延迟消息。postDelayed()方法的第一个参数是一个Runnable对象,它表示我们要执行的任务。第二个参数是延迟的时间,单位是毫秒。

问题来了

我们在发送延迟消息的时候,可能会遇到一个问题,那就是我们可能不需要这条消息了。例如,我们在页面跳转的时候,我们可能不希望这条消息被执行。

根据what移除消息

我们可以使用removeMessages()方法来移除消息。removeMessages()方法的第一个参数是what值,它表示我们要移除的消息的what值。第二个参数是runnable对象,它表示我们要移除的消息的runnable对象。

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 发送一条延迟消息,10秒后执行
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 这里执行你要做的事情
            }
        };
        handler.postDelayed(runnable, 10000);

        // 在页面跳转的时候,移除这条消息
        handler.removeMessages(0, runnable);
    }
}

上面的代码中,我们在发送延迟消息的时候,同时保存了runnable对象。然后在页面跳转的时候,我们使用removeMessages()方法来移除这条消息。

根据消息的Runnable移除消息

我们还可以根据消息的Runnable对象来移除消息。这种方法的好处是,我们可以移除所有使用这个Runnable对象的消息。

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 发送一条延迟消息,10秒后执行
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // 这里执行你要做的事情
            }
        };
        handler.postDelayed(runnable, 10000);

        // 在页面跳转的时候,移除所有使用这个Runnable对象的消息
        handler.removeCallbacks(runnable);
    }
}

上面的代码中,我们在发送延迟消息的时候,同时保存了runnable对象。然后在页面跳转的时候,我们使用removeCallbacks()方法来移除所有使用这个Runnable对象的消息。

源码

public class Handler {

    private MessageQueue mQueue;
    private Looper mLooper;
    private Message mMessage;

    public Handler() {
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
    }

    public void handleMessage(Message msg) {
        // 这里执行你要做的事情
    }

    public final boolean sendMessage(Message msg) {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return mQueue.enqueueMessage(msg, delayMillis);
    }

    public final void removeMessages(int what, Object object) {
        mQueue.removeMessages(this, what, object);
    }

    public final void removeCallbacks(Runnable r) {
        mQueue.removeCallbacks(this, r);
    }

}

public class MessageQueue {

    private Message mMessages;

    public boolean enqueueMessage(Message msg, long delayMillis) {
        Message p = mMessages;
        if (p == null || delayMillis == 0) {
            msg.when = SystemClock.uptimeMillis();
            msg.next = p;
            mMessages = msg;
        } else {
            long when = SystemClock.uptimeMillis() + delayMillis;
            while (p != null) {
                if (p.when > when) {
                    break;
                }
                p = p.next;
            }
            msg.when = when;
            msg.next = p;
            if (p != null) {
                p.prev = msg;
            }
        }
        return true;
    }

    public void removeMessages(Handler h, int what, Object object) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
                if (p.target == h && p.what == what && (object == null || p.obj == object)) {
                    if (p.prev != null) {
                        p.prev.next = p.next;
                    } else {
                        mMessages = p.next;
                    }
                    if (p.next != null) {
                        p.next.prev = p.prev;
                    }
                    p.next = null;
                    p.prev = null;
                    p.target = null;
                    p.obj = null;
                    return;
                }
                p = p.next;
            }
        }
    }

    public void removeCallbacks(Handler h, Runnable r) {
        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
                if (p.target == h && p.callback == r) {
                    if (p.prev != null) {
                        p.prev.next = p.next;
                    } else {
                        mMessages = p.next;
                    }
                    if (p.next != null) {
                        p.next.prev = p.prev;
                    }
                    p.next = null;
                    p.prev = null;
                    p.target = null;
                    p.obj = null;
                    p.callback = null;
                    return;
                }
                p = p.next;
            }
        }
    }

}