Handler机制(一)——Handler运行流程分析

1 概述

Handler机制是Android的异步消息处理机制,用于在线程间传递消息,主要涉及到四部分:Handler、Looper、Message和MessageQueue。其中Handler是消息的发送者和处理者;Message是消息主体;MessageQueue是消息队列,Handler发送的消息都会放入MessageQueue中等待处理;Looper是MessageQueue的管理者,里面有一个loop方法,无限循环的从MessageQueue中取出需要处理的消息(如果有),并交个Handler处理。
这里有几个概念,一个线程只能有一个Looper对象和MessageQueue对象,而一个线程可以创建多个Handler对象,每一个Handler发送的消息只能由自己进行处理。通常的使用时主线程创建Handler对象,子线程使用这个Handler对象发送消息,由于这个Handler绑定的是主线程的Looper,所以会进入主线程的MessageQueue,也会由主线程的Looper分发给这个Handler回调他的handleMessage方法对消息进行处理。其中的原理看完下面的源码分析就可以理解了。

2 Handler对象创建问题

Android的UI线程是应用的主线程,是非线程安全的。Android规定,所有关于UI的更新都必须在主线程中执行,如果尝试在子线程中执行UI的更新操作会导致程序崩溃。

public class MainActivity extends AppCompatActivity {
   

    private Handler handler1;
    private Handler handler2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler1 = new Handler();
        new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                handler2 = new Handler();
            }
        }).start();
    }
}

上面尝试在主线程和子线程中都创建一个Handler的实例,运行程序后会发现程序崩溃,日志打印如下:

E/AndroidRuntime: FATAL EXCEPTION: Thread-2
    Process: com.xy.handlertest, PID: 3524
    java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-2,5,main] that has not called Looper.prepare()
        at android.os.Handler.<init>(Handler.java:227)
        at android.os.Handler.<init>(Handler.java:129)
        at com.xy.handlertest.MainActivity$1.run(MainActivity.java:21)
        at java.lang.Thread.run(Thread.java:923)

报错显示无法在子线程中创建handler,原因是因为该线程中没有调用Looper.prepare()方法。
接下来可以进行改造,在子线程中调用该方法。

public class MainActivity extends AppCompatActivity {
   

    private Handler handler1;
    private Handler handler2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler1 = new Handler();
        new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                Looper.prepare();
                handler2 = new Handler();
            }
        }).start();
    }
}

发现程序正常运行。接下来探究一下为什么需要调用Looper.prepare()方法后,才能够创建Handler的实例。可以查看Handler类的无参构造方法:

@Deprecated
public Handler() {
   
    this(null, false);
}

可以看到,这里调用的是有两个参数重载的构造函数。同时,这里标志了废除的注解,说明这个方法是不建议使用的,原因就像是上面的例子一样,如果该线程没有调用过Looper的prepare()方法,就会出现程序崩溃,所以这里不建议使用无参构造方法。至于Looper的prepare()方法中做了什么,接着往下看。

public Handler(@Nullable Callback callback, boolean async) {
   
    if (FIND_POTENTIAL_LEAKS) {
   
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass(<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值