Android Handler消息机制详解6

79 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

四.代码实现

a.创建一个Handler

//创建Handler
private final UIHandler mHandler = new UIHandler(this);
private static class UIHandler extends Handler {

    private static final int MSG_UPDATE_BG = 1;
    //防止内存泄露,使用弱引用,否则Handler会持有Activity的强引用,影响内存回收
    private final WeakReference<DisplayActivity> mActivity;

    private UIHandler(DisplayActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        DisplayActivity activity = mActivity.get();
        if (activity == null) {
            FLog.e(TAG,"activity is null, handleMessage return");
            super.handleMessage(msg);
            return;
        }
        switch (msg.what) {
            case MSG_UPDATE_BG:
                activity.updateUI(msg.arg1, msg.arg2, (boolean) msg.obj);
                break;
            default:
                super.handleMessage(msg);
                break;
        }
    }
}

b.使用Handler发送消息

//简单的消息只传递what
mHandler.sendEmptyMessageDelayed(UIHandler.MSG_UPDATE_BG, 500);
//通过obtainMessage,可以传递what,arg1,arg2及obj参数
mHandler.sendMessage(mHandler.obtainMessage(UIHandler.MSG_UPDATE_BG1,
                display, statusCode, false));

c.处理消息

   @Override
    public void handleMessage(Message msg) {
        DisplayActivity activity = mActivity.get();
        if (activity == null) {
            FLog.e(TAG,"activity is null, handleMessage return");
            super.handleMessage(msg);
            return;
        }
        switch (msg.what) {
            case MSG_UPDATE_BG:
                activity.updateUI(msg.arg1, msg.arg2, (boolean) msg.obj);
                break;
            default:
                super.handleMessage(msg);
                break;
        }
    }

      上面已经一步步的解释了一个消息从发送到处理的整个流程,用流程图概况Handler的工作流程如下:

image.png

五.ThreadLocal

      在主线程里面创建多个Handler的时候,为什么都能更新UI?换句话说,为什么都能共享主线程的Looper?那么就用到了ThreadLocal这个东西了,一起看一下。
对ThreadLocal的误解:
1.ThreadLocal为解决多线程程序的并发问题提供了一种新的思路
2.ThreadLocal的目的是为了解决多线程访问资源时的共享问题
官方注释:

/**
 * This class provides thread-local variables.  These variables differ from
 * their normal counterparts in that each thread that accesses one (via its
 * {@code get} or {@code set} method) has its own, independently initialized
 * copy of the variable.  {@code ThreadLocal} instances are typically private
 * static fields in classes that wish to associate state with a thread (e.g.,
 * a user ID or Transaction ID).
*/

      从注释可以看到:ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程的上下文。

      概括如下:

      1.ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。

      2.ThreadLocal的设计初衷就是为了提供线程内部的局部变量,方便在本线程内随时随地的读取,并且与其他线程隔离。

      3.ThreadLocal实现了一个线程相关的存储,即每个线程都有自己独立的变量。所有的线程都共享这一个ThreadLocal对象,并且当一个线程的值发生改变之后,不会影响其他的线程的值。