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

原文地址:https://www.cnblogs.com/hellokitty2/p/10801429.html

时间: 2024-10-18 21:57:33

Android 消息处理机制的相关文章

android消息处理机制原理解析

在android开发过程中相信屌丝程序员们都用过Handler来处理一些逻辑任务,比如发送延迟消息处理业务等逻辑,我们常用的图片加载缓存库ImageLoader和Picasso等内部也是通过Handler来最终有后台加载线程切换到主线程(UI线程)来更新页面的,今天就趁着离职有点儿时间就抽空的分析了下它的一点源码,在此总结出来.闲言少叙,书归正传! 先来谈谈Looper: Looper从源码上来看就是一个普通的Java类,它在消息机制中,顾名思义,就是一个消息循环的角色.有时候读源码,我习惯性的

【Android 开发】: Android 消息处理机制之一: Handler 与 Message

最近几讲内容,我们学习了Android中关于多线程的一些知识,上一讲我们讲解了异步任务 AsyncTask 的操作,Android中还提供了其他的线程操作,如Handler Message MessageQueue Looper 等模块,这些就是Android中的消息处理机制.这部分内容是Android学习过程中的重点和难点.    现在我们就来学习一下Android的消息处理,以及剖析一下相关类如Handler和Message类的源代码,同时使用他们来更新UI主线程的操作.因为Android的

Android -- 消息处理机制源码分析(Looper,Handler,Message)

android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因此我没将其作为核心类.下面一一介绍: Looper Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程.所谓Looper线程就是循环工作的线程.在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Lo

Android架构分析之Android消息处理机制(二)

作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:4.4.2 在上一篇文章中我们看了一个使用Handler处理Message消息的例子,本文我们来分析一下其背后隐藏的Android消息处理机制. 我们可能比较熟悉Windows操作系统的消息处理模型: while(GetMessage(&msg,NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } 1.消息

Android消息处理机制(源码分析)

前言 虽然一直在做应用层开发,但是我们组是核心系统BSP,了解底层了解Android的运行机制还是很有必要的.就应用程序而言,Android系统中的Java应用程序和其他系统上相同,都是靠消息驱动来工作的,它们大致的工作原理如下: 1. 有一个消息队列,可以往这个消息队列中投递消息. 2. 有一个消息循环,不断从消息队列中取出消息,然后处理 . 为了更深入的理解Android的消息处理机制,这几天空闲时间,我结合<深入理解Android系统>看了Handler.Looper.Message这几

Android消息处理机制:源码剖析Handler、Looper,并实现图片异步加载

引言 我们在做 Android 开发时,常常需要实现异步加载图片/网页/其他.事实上,要实现异步加载,就需要实现线程间通信,而在 Android 中结合使用 Handler.Looper.Message 能够让不同的线程通信,完成异步任务.虽然 Android 官方为我们提供了 AsyncTask 类来完成异步任务,但这个类存在许多问题,并不好用,而且,AsyncTask 也是通过 Handler 和 Thread 来实现异步加载的,所以学习这方面的知识是有必要的 本文讲解思路大致如下:绘制 A

Android架构分析之Android消息处理机制(三)

作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:4.4.2 本文我们来分析AndroidUI线程即主线程是怎样实现对消息的处理的. UI线程的实现类定义在frameworks/base/core/java/android/app/ActivityThread.java文件中.我们来看Android对ActivityThread类的说明 : 130/** 131 * This manages the execution of the main

Android消息处理机制

文章出处:http://www.cnblogs.com/qingblog/archive/2012/06/27/2566021.html Google参考了Windows的消息处理机制,在Android系统中实现了一套类似的消息处理机制.学习Android的消息处理机制,有几个概念(类)必须了解: 1.       Message 消息,理解为线程间通讯的数据单元.例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程. 2.       Message Q

7.1 基础知识Android消息处理机制

1. Android消息处理机制: Handler, MessageQueue, Looper, Thread 线程概念 : 一个应用程序运行时它的主体被称为进程, 一个进程内部可以有多个线程, 线程共享进程的资源 线程间通信 在android系统中是怎么封装通讯的,假如存在两个线程A和B,如果A线程要告诉B线程一些消息,怎么实现? A进程怎么发发消息?(1)构造消息,消息里面有数据信息和处理函数(2)发消息:这两个步骤在android源码中被封装成Handler 消息在android中被封装为