美文网首页
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