Tip---Android的消息机制

112 阅读4分钟

##底层要点简述

详细的,可以看一下这篇博客给ThreadLocal的关键分析Android(Java) | 如何使程序实现线程安全(拓展分析:ThreadLocal、重排序、volatile/final)

  • 首先,底层实现了一个线程本地存储,叫ThreadLocal区域, 一个主线程以及它对应的所有子线程,共享同一个 ThreadLocal对象, 这个ThreadLocal对象中可以说逻辑上维护着一个内存空间, 这个内存空间为不同的线程一 一 对应地维护一套数据副本【t.thread】每一套数据副本对应着一个线程 (有多少线程共享这个ThreadLocal对象,ThreadLocal对象就准备多少套数据副本createMap(t, value)】), 每一套数据副本在这里可以具体化为一个Object数组

不同线程访问同一个ThreadLocal的get方法, 比如对应线程的Looper, ThreadLocal的索引值(key)就是ThreadLocal为每个线程创建的独立的threadLocals实例(ThreadLocal<Looper>对应); value就是不同线程自己的Looper对象;

  • 而主线程及其所有子线程都可以开辟自己的Looper, 每一个Looper都要绑定在一个Handler上,(如下方图1图2) 然后这些个每个单独的Looper, 都是Looper对应线程共享的ThreadLocal中某一个数据副本中的一个项的value, 这个项有keyvalue两部分, value是刚说的每一个线程对应的Looper, 然后这个唯一的静态的Looper对象了关联着一个MessageQueue

####整个消息机制的工作流程常规表述

  • 首先在需要传递消息的地方,我们构造一个**Message(消息)对象, 此时Message中会有自己的一个ID, 然后我们把需要传递的数据设置在这个Message里面, 借助HandlersendMessage()** 方法将**Message传递到MessageQueue**中, 此时MessageQueue通过调用MessageQueue.enqueueMessage()MessageQueue自身中添加这条发送过来的Message

  • **MessageQueue(消息队列)中存放着诸多相关联的Handler**发送过来的Message, 其内部通过单链表的数据结构来维护消息列表, 等待Looper的抽取。

  • Looper(消息泵)通过Looper.loop() 不断轮询MessageQueue, 调用MessageQueue.next(),从MessageQueue中抽取队头的Message, 接着调用这个Message对应的HandlerdispatchMessage(), 将该Message传递分发给对应的Handler

  • 目标Handler收到Message后调用handlerMessage()处理这个消息。

图0

##附图 图1

#机制中相关元素的数量关系

Thread(线程):负责调度整个消息循环,即消息循环的执行场所。 存在关系:

  • 每个Thread(包括主线程、子线程)都可有且只能有一个Looper,可以有多个Handler;
  • Looper有一个MessageQueue,可以处理来自多个(绑定同一个Looper)Handler的Message;
  • MessageQueue有一组待处理的Message,这些Message可来自不同的Handler;
  • Message中记录了负责发送和处理消息的Handler; 一个Message对应一个Handler, 一个Handler可以发送多个Message;
  • Handler绑定Looper(默认绑定主线程)和MessageQueue;

图2

##参考资料:

#实用要点总结

  • 主线程创建时,会自动创建一个默认的Looper对象,而Looper对象的建立将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper,需要的时候通过prepar函数实现。
  • 每一个MessageQueue都不能脱离Looper而存在, Looper对象的创建是通过prepare函数来实现的。
  • 同时每一个Looper对象和一个线程关联。 ·通过调用Looper.myLooper()可以获得当前线程的Looper对象,创建一个Looper对象时,会同时创建一个messagequeue对象。
  • 除了主线程有默认的Looper, 其他子线程默认是没有MessageQueue对象的,默认不能接受Message。
  • 如需要接受,子线程需自己定义 一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。 Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。
  • 以上理论详见 —— Android之Message、handler学习
  • 相关博客 ——通信之线程间通信(上)-handler

public class HandlerThreadActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        TextView textView = (TextView) findViewById(R.id.tv);
        textView.setText("HandlerThreadActivity.class");
 
        HandlerThread handlerThread = new HandlerThread("HandlerThread");
        handlerThread.start();
 
        Handler mHandler = new Handler(handlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.d("HandlerThreadActivity.class","uiThread2------"+Thread.currentThread());//子线程
            }
        };
 
        Log.d("HandlerThreadActivity.class","uiThread1------"+Thread.currentThread());//主线程
        mHandler.sendEmptyMessage(1);
    }
}