您的位置:首页 > 移动开发 > Android开发

android消息机制自我理解

2015-05-07 10:31 288 查看
android消息机制基本理解:

Android通过Looper、Handler来实现消息循环机制。Android的消息循环是针对线程的,每个线程都可以有自己的消息队列和消息循环。Android系统中的Looper负责管理线程的消息队列和消息循环。通过Looper.myLooper()得到当前线程的Looper对象,通过Looper.getMainLooper()得到当前进程的主线程的Looper对象。接下来我们一一理解这些对象。

1,Message

* Defines a message containing a description and arbitrary data object that can be

* sent to a {@link Handler}. This object contains two extra int fields and an

* extra object field that allow you to not do allocations in many cases.

这一段是源码中对Message的解释,定义一个包含能被Handler发送的消息对象。OK,我们来看下它比较重要的成员变量。

(1)target 指定发送和接受Message的Handler对象。

(2)callback 这个成员变量其实是一个Runnable对象,我们经常用Handler.post(Runnable a),Runnable a对象最终也是封装

成一个Message对象进行传递的。如果是普通的Message对象 callback为null,如果是通过post(Runnbale a)这种方式

最终在MessageQueue中存放的Message对象 的callback就是刚才post的runnable对象

(3)Bundle data 这个成员变量允许用户传递更多的数据信息

(4) long when 什么时候发送该消息

(5) Message next 在MessageQueue中获取该Messge的下一个Messge对象

2,MessageQueue

顾名思义存放消息的对列,Handler通过此队列存放和获取Message消息。2个重要方法

(1) final boolean enqueueMessage(Message msg, long when)

handler发送消息的时候通过此方法,将Message信息加入消息队列中

(2) final Message next()

获取下一个Message

3,Looper

/**

* Class used to run a message loop for a thread. Threads by default do

* not have a message loop associated with them; to create one, call

* {@link #prepare} in the thread that is to run the loop, and then

* {@link #loop} to have it process messages until the loop is stopped.

** /

上面一段是源码中对Looper的定义。除主线程外,其他线程是没有Looper对象,需要使用者自己去创建,

它主要的作用就是不断的处理消息直到它停止。那为什么主线程的Looper对象而其他线程没有?Ok,我们看下

主线程的源码,ActivityThread其实是含有main函数的,来看下主函数的代码。

public static void main(String[] args) {

SamplingProfilerIntegration.start();

// CloseGuard defaults to true and can be quite spammy. We

// disable it here, but selectively enable it later (via

// StrictMode) on debug builds, but using DropBox, not logs.

CloseGuard.setEnabled(false);

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

if (sMainThreadHandler == null) {

sMainThreadHandler = new Handler();

}

ActivityThread thread = new ActivityThread();

thread.attach(false);

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");

}

我们看到在主线程在创建的时候就有2行关于Looper的代码

(1)

/**

* Initialize the current thread as a looper, marking it as an

* application's main looper. The main looper for your application

* is created by the Android environment, so you should never need

* to call this function yourself. See also: {@link #prepare()}

*/

public static void prepareMainLooper() {

prepare();

setMainLooper(myLooper());

myLooper().mQueue.mQuitAllowed = false;

}

这个方法功能就是初始化一个Looper对象,当然Looper对象在被创建的时候也同时构建了一个MessageQueue对象,注释

告诉你已经创建了一个Looper对象给主线程,使用者无需手动创建了。什么时候创建的呢?在主线程创建的时候。

(2)
Looper.loop();

/**

* Run the message queue in this thread. Be sure to call

* {@link #quit()} to end the loop.

*/

public static void loop() {

Looper me = myLooper();

if (me == null) {

throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");

}

MessageQueue queue = me.mQueue;

// Make sure the identity of this thread is that of the local process,

// and keep track of what that identity token actually is.

Binder.clearCallingIdentity();

final long ident = Binder.clearCallingIdentity();

while (true) {

Message msg = queue.next(); // might block

if (msg != null) {

if (msg.target == null) {

// No target is a magic identifier for the quit message.

return;

}

long wallStart = 0;

long threadStart = 0;

// This must be in a local variable, in case a UI event sets the logger

Printer logging = me.mLogging;

if (logging != null) {

logging.println(">>>>> Dispatching to " + msg.target + " " +

msg.callback + ": " + msg.what);

wallStart = SystemClock.currentTimeMicro();

threadStart = SystemClock.currentThreadTimeMicro();

}

msg.target.dispatchMessage(msg);

if (logging != null) {

long wallTime = SystemClock.currentTimeMicro() - wallStart;

long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;

logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

if (logging instanceof Profiler) {

((Profiler) logging).profile(msg, wallStart, wallTime,

threadStart, threadTime);

}

}

// Make sure that during the course of dispatching the

// identity of the thread wasn't corrupted.

final long newIdent = Binder.clearCallingIdentity();

if (ident != newIdent) {

Log.wtf(TAG, "Thread identity changed from 0x"

+ Long.toHexString(ident) + " to 0x"

+ Long.toHexString(newIdent) + " while dispatching to "

+ msg.target.getClass().getName() + " "

+ msg.callback + " what=" + msg.what);

}

msg.recycle();

}

}

}

loop()方法的while(true)循环使Looper对象有不断从MessageQueue中取消息的能力,

Message msg = queue.next(); //此行代码正式不断取消息

msg.target.dispatchMessage(msg); // 通过target即Handler对象发送消息

如果非主线程,需要像主线程这样用到消息,那怎么处理呢? 上面2个方法就是关键,首先需要new 一个Looper对象,然后需要调用Loop()方法。

4,Handler

介绍了这么多,接下来讲一下用得最多的Handler方法,我们不管是sendMessge或者post(Runnable a)最懂都会调用到

方法 :

public boolean sendMessageAtTime(Message msg, long uptimeMillis)

在什么时间发送该消息,通过上面介绍的MessageQueue方法enqueueMessage(msg, uptimeMillis); 将消息放到消息队列。

这是存放消息,接下来看处理消息的部分。Looper对象不断从MessageQueue中取消息,然后调用Handler的dispatchMessage(Message msg) 方法来处理消息。看下具体方法:

/**

* Handle system messages here.

*/

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

首先判断Message对象中的callback是否为null,如果callback不为null,此Message对象就包含一个Runnable,直接启动该Runnable对象;如果Callback为null,那Message只是单纯传递的数据,通过Message内部对象mCallback来处理。这个mCallback也就是我们new
Handler时传递的一个对象。具体定义如下:

public interface Callback {

public boolean handleMessage(Message msg);

}

OK,关于消息机制就说这么多,下面是从网上扒的图,便于大家理解

下面是消息机制中几个重要成员的关系图:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐