Handler原理

Handler

Handler:快递员(属于某个快递公司的职员)
Message:包裹(可以放置很多东西的箱子)
MessageQueue:快递分拣中心(分拣快递的传送带)
Looper:快递公司(具有处理包裹去向的管理中心)
情景分析:在子线程中更新主线程的UI

其中的原理机制可以形象的理解为:

某天,你想给朋友寄一件礼物,首先你拿个箱子装好礼物并包裹好,下单叫了某家的快递员上门取件,快递员揽收你的包裹后,会将包裹送往快递分拣中心,等待配送车送出你的包裹。等配送车来了,就按照你的包裹地址信息,送到指定地方站点,然后分派给相应的快递员,将你的包裹送到你的朋友手里。
这整个邮寄包裹的过程可以形象的理解为Handler的工作机制原理,下面还原一下实际工作过程:

某时,你想刷新主界面的TextView,无奈你不在主线程,此时你就会包装好Message,然后声明一个Handler,让Handler将你的Message送往主线程(Looper),Handler将你的Message送到主线程后,还需要排队等待,等轮到你的时候,主线程就会告诉Handler,这个Message可以处理了,你负责分发一下,于是,Handler将该Message分发到相应的回调或者handleMessage( ) 方法中,于是,你就在该方法中更新了UI。

仅举例子的原文链接:https://blog.csdn.net/luoyingxing/article/details/86500542

AsyncTask

AsyncTask内部是线程池、线程和handler来实现的

核心方法:

onPreExecute():在主线程处理一些准备工作。
doInBackgroud(Params…Params):在主线程中处理异步任务耗时任务,可以通过publishProgress方法来更新任务的进度。
onProgressUpdate(Progress…values):在主线程中执行,当后台任务进度改变触发回调。
onPostExecute(Result result):在主线程中,异步任务技术触发回调,其中result就是后台任务的返回值。

Handler作用:
就是主要发送和处理消息的。

因为在Android中,主线程不建议做耗时的操作,子线程不建议更新UI,但是Android开发,其实就是搭建好页面,将服务器的数展示到页面上,所以我网络请求使用会非常频繁,而网络请求属于耗时操作,需要放到子线程完成,但一般情况下也不会通过子线程更新UI,需要将请求成功的数据发送到主线程进行UI更新,使用场景:用于线程通信,所以一般会使用到handler。

Handler的使用分为4个步骤
自定义Handler子类(继承Handler类),复写handleMessage()方法
在主线中创建Handler实例
创建所需的消息对象
在子线程中发送消息到消息队列中在handleMessage处理消息(更新UI)

Handler执行流程
首先handler作为任务执行者,一般创建在主线程,当子线程有需要发送的数据,通过创建message对象,使用handler对象将信息发送到messagequeue,messsagequeue遵循了队列先进先出的原则,当主线程的looper循环信息的时候,会按照messsagequeue队列的顺序循环信息,并将消息给任务执行者handler去执行任务。

Handler执行原理
Handler创建完成后,内部的looper以及MessageQueue就可以和Handler一起协同工作,然后通过Handler的post方法将一个Runnable投递到Handler内部的Looper中去处理,也可以通过Handler的send方法发送一个信息,这个信息会在looper中做处理。Post最终也是通过send来完成的,当Handler的send方法被调用时,他会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列中,然后looper发现有新消息到来时,就会处理这个消息,最终消息中的Runnable或者Handler的handlerMessage方法就会被调用。Loopper试运行在Handler所在的线程,所以就把业务逻辑切换到主线程了

Looper他是循环处理消息的发动机,永不停息(永动鸡)死循环。它不断的从消息队列MessageQueue中取出的消息,处理,然后分发处理事件。
所以形成了一个Looper去MessageQueue里面取消息,处理消息的一个流程。

每个线程都可以且只能绑定一个Looper。主线程之所以能处理消息,也是因为在APP启动时,在ActivityThread中的main()方法中就已经启动了Looper循环。

Looper的工作原理
Looper在Android的消息机制中扮演着消息循环的角色,就是不停的从MessageQueue中查看是否有新消息,如果有消息就立刻处理,否则就一直阻塞在那里。首先在构造方法中创建一个MessageQueue即队列信息,然后将当前的对象保存起来,Looper除了prepare方法外还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper使用的,其本质也是通过prepare方法来实现的。由于主线程的Looper比较特殊,所以Looper提供了一个getMainLooper方法,通过它可以再任何地方获取到主线程的Looper,Looper也是可以退出的
Looper的处理消息的循环还是挺简单的,就是拿出消息,然后分发,然后回收

Looper源码

public static void loop() {
    final Looper me = myLooper();   //获得当前的Looper
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    
    final MessageQueue queue = me.mQueue;  //获取当前Looper的消息队列
    //......

    for (;;) {
        Message msg = queue.next();  //取出队头的消息
        if (msg == null) {
            // 如果消息为空,则跳过,继续执行下一个message
            return;
        }
        //......
        try {
            msg.target.dispatchMessage(msg);
            //......
        } finally {
           //......
        }
       //......
        msg.recycleUnchecked();  //回收可能正在使用的消息
    }
}

总结
Handler机制可以简述为:
Handler将Message发送到Looper的消息队列中,即MessageQueue,等待Looper的循环读取Message,处理Message,然后调用Message的target,即附属的Handler的dispatchMessage()方法,将该消息回调到handleMessage()方法中,然后完成更新UI操作。

Android启动一个App进程后一直不会退出去,为什么?
和Android的Ams管理有关系,与Application管理有关系
Handler维持了自己的的一个ooper死循环,不会退出去的,所以Handler是“心跳机制”

Handler类
很多send的方法,最终调用了自己的enqueueMessage这个方法,enqueueMessage它会调用MessageQueue的enqueueMessage,这个过程就是将一个message把它传递给MessageQueue里面里面节点的一个过程(接收消息链表数据结构)所以sendMessage最终就是传递消息的,那么MessageQueue干嘛的?
看一下源码

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

    public Handler(Callback callback, boolean async) {
   
      // 不相关代码
       ......
        //得到当前线程的Looper,其实就是调用的sThreadLocal.get
        mLooper = Looper.myLooper();
        // 如果当前线程没有Looper就报运行时异常
        if (mLooper == null) {
   
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        // 把得到的Looper的MessagQueue让Handler持有
        mQueue = mLooper.mQueue;
        // 初始化Handler的Callback,其实就是最开始图中的回调方法的2
        mCallback = callback;
        mAsynchronous = async
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值