Handler的初级、中级、高级问法,有java基础学android

本文深入探讨了Android中的Handler机制,包括Handler的工作流程、如何在主线程中访问网络、为何不建议在子线程中操作UI、子线程如何通过Handler通知主线程更新UI、Looper的死循环原理以及为何不会导致应用卡死。文章还讨论了主线程Looper的退出条件,Handler的消息处理顺序,并提供了相关面试问题和解答。
摘要由CSDN通过智能技术生成
  1. Handle同步屏障机制

  2. Handler的锁相关问题

  3. Handler中的同步方法

  • Handler在系统以及第三方框架的一些应用
  1. HandlerThread

  2. IntentService

  3. 如何打造一个不崩溃的APP

  4. Glide中的运用

Handler的源码和常见问题的解答

下面来看一下官方对其的定义:

A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue.

Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler it is bound to a Looper.

It will deliver messages and runnables to that Looper’s message queue and execute them on that Looper’s thread.

大意就是Handler允许你发送Message/Runnable到线程的消息队列(MessageQueue)中,每个Handler实例和一个线程以及那个线程的消息队列相关联。当你创建一个Handler时应该和一个Looper进行绑定(主线程默认已经创建Looper了,子线程需要自己创建Looper),它向Looper的对应的消息队列传送Message/Runnable同时在那个Looper所在线程处理对应的Message/Runnable。下面这张图就是Handler的工作流程

Handler工作流程图

可以看到在Thread中,Looper的这个传送带其实就一个死循环,它不断的从消息队列MessageQueue中不断的取消息,最后交给Handler.dispatchMessage进行消息的分发,而Handler.sendXXX,Handler.postXXX这些方法把消息发送到消息队列中MessageQueue,整个模式其实就是一个生产者-消费者模式,源源不断的生产消息,处理消息,没有消息时进行休眠。MessageQueue是一个由单链表构成的优先级队列(取的都是头部,所以说是队列)

前面说过,当你创建一个Handler时应该和一个Looper进行绑定(绑定也可以理解为创建,主线程默认已经创建Looper了,子线程需要自己创建Looper),因此我们先来看看主线程中是如何处理的:

//ActivityThread.java

public static void main(String[] args) {

···

Looper.prepareMainLooper();

···

ActivityThread thread = new ActivityThread();

thread.attach(false, startSeq);

if (sMainThreadHandler == null) {

sMainThreadHandler = thread.getHandler();

}

if (false) {

Looper.myLooper().setMessageLogging(new

LogPrinter(Log.DEBUG, “ActivityThread”));

}

// End of event ActivityThreadMain.

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

Looper.loop();

throw new RuntimeException(“Main thread loop unexpectedly exited”);

}

可以看到在ActivityThread中的main方法中,我们先调用了Looper.prepareMainLooper()方法,然后获取当前线程的Handler,最后调用Looper.loop()。先来看一下Looper.prepareMainLooper()方法

//Looper.java

/**

  • Initialize the current thread as a looper, marking it as an

  • application’s main looper. The main looper for your application

  • is created by the Android environment, so you should never need

  • to call this function yourself. See also: {@link #prepare()}

*/

public static void prepareMainLooper() {

prepare(false);

synchronized (Looper.class) {

if (sMainLooper != null) {

throw new IllegalStateException(“The main Looper has already been prepared.”);

}

sMainLooper = myLooper();

}

}

//prepare

private static void prepare(boolean quitAllowed) {

if (sThreadLocal.get() != null) {

throw new RuntimeException(“Only one Looper may be created per thread”);

}

sThreadLocal.set(new Looper(quitAllowed));

}

可以看到在Looper.prepareMainLooper()方法中创建了当前线程的Looper,同时将Looper实例存放到线程局部变量sThreadLocal(ThreadLocal)中,也就是每个线程有自己的Looper。在创建Looper的时候也创建了该线程的消息队列,可以看到prepareMainLooper会判断sMainLooper是否有值,如果调用多次,就会抛出异常,所以也就是说主线程的Looper和MessageQueue只会有一个。同理子线程中调用Looper.prepare()时,会调用prepare(true)方法,如果多次调用,也会抛出每个线程只能由一个Looper的异常,总结起来就是每个线程中只有一个Looper和MessageQueue。

//Looper.java

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

再来看看主线程sMainThreadHandler = thread.getHandler(),getHandler获取到的实际上就是mH这个Handler。

//ActivityThread.java

final H mH = new H();

@UnsupportedAppUsage

final Handler getHandler() {

return mH;

}

mH这个Handler是ActivityThread的内部类,通过查看handMessage方法,可以看到这个Handler处理四大组件,Application等的一些消息,比如创建Service,绑定Service的一些消息。

//ActivityThread.java

class H extends Handler {

···

public void handleMessage(Message msg) {

if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

switch (msg.what) {

case BIND_APPLICATIO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值