Android 消息处理机制
1.消息处理机制简介
主要用于进程内线程之间的通信,主线程一般调用looper()进行循环等待处理消息,其它线程向它发消息并指定消息的处理方法。
(1)涉及文件包括frameworks中的:
Looper.java
Handler.java
MessageQueue.java
Message.java
android_os_MessageQueue.cpp
...
涉及文件包括system中的:
Looper.h
Looper.cpp
(2)涉及native处理机制
使用pipe加epoll机制实现消息队列的睡眠和唤醒进程的功能,同时利用epoll的timeout特性可以指定消息延期多长时间后执行。
2.消息发送流程
enqueueMessage //MessageQueue.java nativeWake(mPtr); android_os_MessageQueue_nativeWake //android_os_MessageQueue.cpp nativeMessageQueue->wake() wake() //system/core/libutils/Looper.cpp write(mWakeWritePipeFd, "W", 1); //只是向消息队列的写端写入一个字符唤醒epoll_wait监听而已
从发送流程可以看出:
Framework中的sendMessage其实并不是通过管道传输的,它只是把msg放到Looper的消息队列上,获取消息的时候是直接从消息队列上获取的,
整个消息传送的过程根本不涉及管道传输数据。native方法中使用pipe进行epoll的作用仅仅是想让java的队列具有睡眠唤醒功能。
3.消息获取流程
loop() //Looper.java queue.next() //MessageQueue.java nativePollOnce(ptr, nextPollTimeoutMillis); //会阻塞在这个函数它,它最终调用的是epoll_wait()进行阻塞。 android_os_MessageQueue_nativePollOnce //android_os_MessageQueue.cpp pollOnce(int timeoutMillis) //system/core/include/utils/Looper.h pollInner //system/core/libutils/Looper.cpp epoll_wait(..., timeoutMillis); //调用系统的epoll_wait函数并设置等待时间为timeoutMillis
4.消息的处理流程
Handler.java中的dispatchMessage方法:
public void dispatchMessage(Message msg) { //优先调用callback,注意它是一个Runnable线程!!执行结果就是启动这个线程去执行。 if (msg.callback != null) { handleCallback(msg); } else { //否则若是创建handler的时候指定了callback,就调用这个callback的handleMessage()进行处理 if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //否则就调用handler的它,它是个空函数,但是可以被重写 handleMessage(msg); } }
5.实验Demo
下面的例子是分别使用这三种处理msg的方法的Demo,在MainActivity.java中实现的
package com.example.mm.app_message_01; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; public class MainActivity extends AppCompatActivity { private static final String TAG = "MessageTest"; private Button mButton = null; private int mClickedCount = 0; private int getMessageCount1 = 0; private int getMessageCount2 = 0; private int getMessageCount3 = 0; /* Test1: success */ private MyThread mThread1 = null; private Handler mHandler1 = null; private MyThread mThread2 = null; private Handler mHandler2 = null; private MyThread mThread3 = null; private Handler mHandler3 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // Code here executes on main thread after user presses button Log.d(TAG, "Clicked: " + mClickedCount); mClickedCount++; mHandler1.sendMessage(new Message()); mHandler2.post(new Runnable() { @Override public void run() { Log.d(TAG, "-2-: Get a new Message, getMessageCount = " + getMessageCount2); getMessageCount2++; } }); mHandler3.sendMessage(new Message()); } }); /*----------------------test1------------------------*/ mThread1 = new MyThread(); mThread1.start(); mHandler1 = new Handler(mThread1.getLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message msg) { Log.d(TAG, "-1-: Get a new Message, getMessageCount = " + getMessageCount1); getMessageCount1++; return true; } }); /*----------------------test2------------------------*/ mThread2 = new MyThread(); mThread2.start(); mHandler2 = new Handler(mThread2.getLooper()); /*----------------------test3------------------------*/ mThread3 = new MyThread(); mThread3.start(); mHandler3 = new MyHandler(mThread3.getLooper()); } class MyThread extends Thread { private Looper mLooper; public void run() { Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Looper.loop(); } Looper getLooper() { if (!isAlive()) { return null; } synchronized (this) { if (mLooper == null) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } return mLooper; } } class MyHandler extends Handler { public MyHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { Log.d(TAG, "-3-: Get a new Message, getMessageCount = " + getMessageCount3); getMessageCount3++; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
测试结果:
/*每当点击屏幕上的Button都会打印下面一组log:*/ 01-01 13:15:22.310 13412-13412/com.example.mm.app_message_01 D/MessageTest: Clicked: 14 01-01 13:15:22.312 13412-13431/com.example.mm.app_message_01 D/MessageTest: -1-: Get a new Message, getMessageCount = 14 01-01 13:15:22.312 13412-13432/com.example.mm.app_message_01 D/MessageTest: -2-: Get a new Message, getMessageCount = 14 01-01 13:15:22.312 13412-13433/com.example.mm.app_message_01 D/MessageTest: -3-: Get a new Message, getMessageCount = 14
6.native的实现很复杂,好像是镜面映射了一个message的queue和java的queue对应。
7.Looper类中只有一个构造函数,它里面new了一个MessageQueue,也就是说MessageQueue是Looper对象的。
参考:
android消息处理机制原理解析:https://blog.csdn.net/chunqiuwei/article/details/52251242
posted on 2019-05-02 00:52 Hello-World3 阅读(1091) 评论(0) 编辑 收藏 举报