美文网首页
Handler源码分析

Handler源码分析

作者: Amy木婉清 | 来源:发表于2021-05-21 16:20 被阅读0次

    MessageQueue:消息队列
    用来存放通过Handler发送的消息
    它是一个按Message的when排序的优先级队列
    Looper:循环器
    负责循环取出Message Queue里面的当前需要处理的Message
    交给对应的Handler进行处理
    处理完后,将Message缓存到消息池中,以备复用

    Message:数据载体

    Message:重要属性

     public int what;//标识(类似于id)
     public int arg1;//保存int数据
     public int arg2;//保存int数据
     public Object obj;//保存任意数据
     public long when;//记录应该被处理的时间值
     Handler target;//用来处理消息的Handler对象,就是发送消息的handler
     Runnable callback; //用来处理消息的回调器(一般不用)
     Message next;//指向下一个Message,用来形成一个链表
     private static Message sPool; //用来缓存处理过的Message,以便复用
    Message obtain() //该方法利用了Message中消息池(sPool)
    
    Runnable的run()什么时候在分线程执行?

    将Runnable传给Thread的构造方法:

    new Thread(new Runnable(){
        public void run(){//在分线程执行
    
        }
    }).start();
    
    Handler: 发送消息 处理消息 移除消息
    public final boolean sendMessage(@NonNull Message msg) {
            return sendMessageDelayed(msg, 0);//延迟消息  延迟时间为0
        }
    
    
     public final boolean sendEmptyMessage(int what)
        {
            return sendEmptyMessageDelayed(what, 0);//发送一个空的延迟消息
        }
    
        public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {//发送不带数据的消息
            Message msg = Message.obtain();
            msg.what = what;
            return sendMessageDelayed(msg, delayMillis);
        }
    
        //发送延迟消息,指定消息,指定延迟时间
        public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
            if (delayMillis < 0) {
                delayMillis = 0;
            }
            return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//当前时间+延迟时间
        }
    
     public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, uptimeMillis);
        }
    
     //将消息添加到消息队列
     public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
            MessageQueue queue = mQueue;
            if (queue == null) {
                RuntimeException e = new RuntimeException(
                        this + " sendMessageAtTime() called with no mQueue");
                Log.w("Looper", e.getMessage(), e);
                return false;
            }
            return enqueueMessage(queue, msg, uptimeMillis);
        }
    
      private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
                long uptimeMillis) {
            msg.target = this;//保存发送消息的handler对象
            msg.workSourceUid = ThreadLocalWorkSource.getUid();
    
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);//调用消息队列保存消息对象
        }
    
     //移除消息
      public final void removeMessages(int what) {
            mQueue.removeMessages(this, what, null);//调用消息队列移除它内部的指定what消息
        } 
    
     //处理消息的回调方法
     public void handleMessage(@NonNull Message msg) {
        }
    
    //
        public void dispatchMessage(@NonNull Message msg) {
            if (msg.callback != null) { //如果消息可以自己处理,让消息自己处理
                handleCallback(msg);
            } else {
                if (mCallback != null) { //如果handler中有回调监听器(即callBack),调用回调器来处理消息
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg); //让Handler的 handleMessage()来处理
            }
        }
    
    MessageQueue:存储消息的以message的when排序的优先级队列
    boolean enqueueMessage(Message msg, long when){}//将message添加到队列中
    
      for (;;) { //将当前消息对象保存到消息队列中一个合适的位置 
                        prev = p;
                        p = p.next;
                        if (p == null || when < p.when) {
                            break;
                        }
                        if (needWake && p.isAsynchronous()) {
                            needWake = false;
                        }
                    } //最终的结果是: 消息队列是按when来排序的
    
     nativeWake(mPtr); //通过本地方法实现对处于等待状态的底层线程
     
     // 取出一个合适的Message对象,可能不会立即返回
     Message next() {
     for (;;) {
                if (nextPollTimeoutMillis != 0) {
                    Binder.flushPendingCommands();
                }
    
                nativePollOnce(ptr, nextPollTimeoutMillis);//本地方法,会导致可能处于等待状态,但不会阻塞主线程
                Message msg = mMessages;//取出消息队列中的第一个消息
                ......
               return msg;//返回
    
    }
    
    }
    
    Looper 从MessageQueue中获取当前需要处理的消息,并交给Handler处理
     //核心方法
     public static void loop() { 
          final Looper me = myLooper(); //得到looper对象
          final MessageQueue queue = me.mQueue; //得到消息队列对象
         // 无限循环 没有break
         for (;;) { 
          Message msg = queue.next(); // 从消息队列中取出消息  might block(可能阻塞)
          ......
          msg.target.dispatchMessage(msg); //调用Handler去分发并处理消息
          msg.recycleUnchecked(); //回收利用message
          }
    }
    
    消息机制与异步任务总结

    在Android中,只有在UIThread(主线程)中才能直接更新页面
    在Android中长时间的工作(联网)都需要在worker Thread中执行
    在分线程获得服务器数据后,需要立即到主线程中去更新界面显示数据

    如何实现线程间通讯?

    1)消息机制:Handler + Thread
    2)异步任务: AsyncTask == Handler + ThreadPool

    相关API
    Message

    Message(消息):线程间通信的数据载体
    1) 对象的创建
    Message.obtain() //有可能是新建的,也有可能是复用的消息池中的
    2)对象的使用
    使用相对较频繁的
    int what //标识
    int args1//存储整形数据
    int args2//存储+整形数据
    Object obj //存储任意类型(对象)数据
    使用不频繁的
    Handler target //保存处理消息的handler对象(发消息的handler)
    long when //消息应该被处理的时间
    Message next //有了此属性Message就可以形成队列
    static Message pool //消息池,缓存用过得消息用于复用
    Runnable CallBack // 用来处理当前消息的回调器

    Handler的使用

    Handler // 发送 处理 移除消息
    1)对象的创建
    new Handler()

    1. 对象的使用
      发送消息
      发即时消息:sendMessage(Message message)
      发延迟消息:sendMessageDelayed(Message message,long delayTime)
      发即时空消息:sendEmptyMessage(int what) //发送内容为空
      发延迟空消息:sendEmptyMessageDelayed(int what,long delayTime)

    处理消息
    void handleMessage(Message msg) //回调方法

    移除消息
    removeMessage(int what) //移除未处理的指定what的message
    removeCallbacksAndMessages(@Nullable Object token) // 传null【removeCallbacksAndMessages(null)】移除所有未处理的消息

    MessageQueue :消息队列

    用来存放通过Handler发送的消息
    它是一个按Message的when排序的优先级队列

    Looper(钩子) 循环器

    负责循环取出MessageQueue里面的当前需要处理的Message
    交给对应的Handler进行处理
    处理完后,将Message缓存到消息池中,以备复用

    消息机制的原理
    image.png image.png
    Handler用于做什么工作?

    1.线程间通信(子线程切换到主线程运行)
    2.延迟的工作
    3.循环定时工作

    AsyncTask的使用

    1.什么是异步任务?
    逻辑上:以多线程的方式完成的功能需求
    API上:指AscyncTask

    AsyncTask的理解

    1)在没有它之前我们可以用Handler+Thread实现一个异步任务的功能
    2)使用AsyncTask也可以实现异步功能
    为什么使用AsyncTask
    1.编码简洁(可以理解为填空题(Async)和问答题的区别)
    2.运行效率高:线程池
    相关API:

    image.png
    Async的基本原理
    image.png
    JSON

    1.JSON是什么?
    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
    本质就是具有特定格式的字符串
    JSON数据已经是客户端与服务器端交互的最常用的选择,已经很少使用xml来进行数据交互了
    json与xml比较的优势:
    简洁 小(省流量、响应快)
    2.JSON的数据格式
    整体结构:
    Json数组:[ ]
    Json对象:{ }
    Jso数组的结构:[value1,value2,value3]
    Json对象的结构:{key1:value1,key2:value2,key3:value3}
    key的数据类型:字符串
    value的数据类型:
    数值
    字符串
    null
    json数组[]
    json对象{}
    例子:

    [1,"ab",[],{"n":123,"b":"abc"}]
    {"name":"TOM","age":12}
    
    image.png

    3.如何解析JSON
    解析技术:
    Android原生API:编程相对麻烦
    Gson框架:编码简洁,项目首选
    解析方向:
    将java对象(包含集合)转换为json格式字符串(服务器)
    将json格式字符串转化为java对象(包含集合)

    相关API
    image.png

    对象根据Key取value 数组根据下标取值

    相关文章

      网友评论

          本文标题:Handler源码分析

          本文链接:https://www.haomeiwen.com/subject/rlavjltx.html