详解Android创建Handler的必备知识点
作者:长安皈故里
普通Handler创建
一般下面这样创建Handler
时AS会进行告警:
删除线提示Handler
的无参构造方法已经被@Deprecated
标记,正确的做法都是使用带Looper
构造参数的构造方法进行Handler
的创建:
这样做的好处是直接指定消息调度在哪个Looper
,而Looper
是通过ThreadLocal
和线程绑定在一起,也就是说,指明了Looper
就能知道当前消息Message
最终会在哪个线程中执行。
而之所以Handler
无参构造方法被废弃的一个原因就是:
它会尝试从当前线程中的ThreadLocal
获取Looper
,主线程会自动帮助我们创建好Looper
自然是没什么问题,但是如果子线程中执行Handler
的创建,而没有手动调用Looper.prepare()
,就会导致崩溃。
异步Handler的使用及创建
异步Handler
有什么作用呢,相比较于普通Handler
,可以获取优先调度执行权,当前,前提是要添加同步屏障消息。
这里解释下同步屏障消息:
同步屏障消息和普通的Message
基本上没啥区别,主要的一个区分点是同步屏障消息Message
的target
属性为null,当从消息队列中取出消息并执行时,会先判断下当前的Message的
target是否为null,如果为null则会从消息队列中优先获取异步消息 进行调度执行。
相应的源码如下:
添加消息屏障的方法为MessageQueue.postSyncBarrier()
,不过这个方法目前是不支持业务方直接进行调用。
上面消息屏障说完了,我们接下来看下异步消息如何创建:异步消息的创建依赖异步Hanlder
的创建。所以我们看下异步Handler
如何进行创建:
@NonNull public static Handler createAsync(@NonNull Looper looper) { if (looper == null) throw new NullPointerException("looper must not be null"); return new Handler(looper, null, true); } @NonNull public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) { if (looper == null) throw new NullPointerException("looper must not be null"); if (callback == null) throw new NullPointerException("callback must not be null"); return new Handler(looper, callback, true); }
Handler
提供了createAsync()
两个重载方法进行创建,最终会将Handler
的mAsynchronous
属性置为true
,然后通过Hanlder
发送消息时,最终会走到Handler.enqueueMessage()
方法:
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { ... if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
可以看到,如果mAsynchronous
属性为true,就将Message
添加FLAG_ASYNCHRONOUS
置为异步消息。不过这个API是只有在SDK>=28以上才能调用,那么消息28的版本如何创建的,这里给出一个非常全面的兼容各个SDK版本的创建异步Handler的方法:
上面的使用讲完了,说下应用了。这个异步消息+消息屏障在系统源码中有一个非常典型的应用场景,那就是界面的绘制:
由于界面的绘制渲染优先级是比较高的,所以添加消息屏障后,将绘制相关的Message
指定为异步方式,就可以优先进行执行。
到此这篇关于详解Android创建Handler的必备知识点的文章就介绍到这了,更多相关Android创建Handler内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!