欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android消息机制Handler深入理解

程序员文章站 2022-03-08 17:44:52
目录概述handler的使用handler架构handler的运行流程源码分析在子线程创建handler主线程的looperlooperhandler分发消息总结概述handler是android消息...

概述

handler是android消息机制的上层接口。通过它可以轻松地将一个任务切换到handler所在的线程中去执行。通常情况下,handler的使用场景就是更新ui。

handler的使用

在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新ui。

public class activity extends android.app.activity {
	private handler mhandler = new handler(){
		@override        
		        public void handlemessage(message msg) {
			super.handlemessage(msg);
			// 更新ui
		}
	}
	;
	@override    
	public void oncreate(bundle savedinstancestate, persistablebundle persistentstate) {
		super.oncreate(savedinstancestate, persistentstate);
		setcontentview(r.layout.activity_main);
		new thread(new runnable() {
			@override            
			             public void run() {
				// 执行耗时任务                ...                
				// 任务执行完后,通知handler更新ui                
				message message = message.obtain();
				message.what = 1;
				mhandler.sendmessage(message);
			}
		}
		).start();
	}
}

handler架构

handler消息机制主要包括:messagequeue、handler、looper这三大部分,以及message。

  • message:需要传递的消息,可以传递数据;
  • messagequeue:消息队列,但是它的内部实现并不是用的队列,而是通过单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能是向消息池投递消息( messagequeue.enqueuemessage)和取走消息池的消息( messagequeue.next)。
  • handler:消息辅助类,主要功能是向消息池发送各种消息事件( handler.sendmessage)和处理相应消息事件( handler.handlemessage);
  • looper:消息控制器,不断循环执行( looper.loop),从messagequeue中读取消息,按分发机制将消息分发给目标处理者。

Android消息机制Handler深入理解

从上面的类图可以看出:

  • looper有一个messagequeue消息队列;
  • messagequeue有一组待处理的message;
  • message中记录发送和处理消息的handler;
  • handler中有looper和messagequeue。

messagequeue、handler和looper三者之间的关系: 每个线程中只能存在一个looper,looper是保存在threadlocal中的。 主线程(ui线程)已经创建了一个looper,所以在主线程中不需要再创建looper,但是在其他线程中需要创建looper。 每个线程中可以有多个handler,即一个looper可以处理来自多个handler的消息。 looper中维护一个messagequeue,来维护消息队列,消息队列中的message可以来自不同的handler。

Android消息机制Handler深入理解

handler的运行流程

在子线程执行完耗时操作,当handler发送消息时,将会调用 messagequeue.enqueuemessage,向消息队列中添加消息。 当通过 looper.loop开启循环后,会不断地从消息池中读取消息,即调用 messagequeue.next, 然后调用目标handler(即发送该消息的handler)的 dispatchmessage方法传递消息, 然后返回到handler所在线程,目标handler收到消息,调用 handlemessage方法,接收消息,处理消息。

Android消息机制Handler深入理解

源码分析

在子线程创建handler

class looperthread extends thread {
	public handler mhandler;
	public void run() {
		looper.prepare();
		mhandler = new handler() {
			public void handlemessage(message msg) {
				// process incoming messages here
			}
		}
		;
		looper.loop();
	}
}

从上面可以看出,在子线程中创建handler之前,要调用 looper.prepare()方法,handler创建后,还要调用 looper.loop()方法。而前面我们在主线程创建handler却不要这两个步骤,因为系统帮我们做了。

主线程的looper

在activitythread的main方法,会调用 looper.preparemainlooper()来初始化looper,并调用 looper.loop()方法来开启循环。

public final class activitythread extends clienttransactionhandler {
	// ...    
	public static void main(string[] args) {
		// ...        
		looper.preparemainlooper();
		// ...        
		looper.loop();
	}
}

looper

从上可知,要使用handler,必须先创建一个looper。

初始化looper:

public final class looper {
	public static void prepare() {
		prepare(true);
	}
	private static void prepare(boolean quitallowed) {
		if (sthreadlocal.get() != null) {
			throw new runtimeexception("only one looper may be created per thread");
		}
		sthreadlocal.set(new looper(quitallowed));
	}
	public static void preparemainlooper() {
		prepare(false);
		synchronized (looper.class) {
			if (smainlooper != null) {
				throw new illegalstateexception("the main looper has already been prepared.");
			}
			smainlooper = mylooper();
		}
	}
	private looper(boolean quitallowed) {
		mqueue = new messagequeue(quitallowed);
		mthread = thread.currentthread();
	}
	// ...
}

从上可以看出,不能重复创建looper,每个线程只能创建一个。创建looper,并保存在 threadlocal。其中threadlocal是线程本地存储区(thread local storage,简称tls),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的tls区域。

开启looper

public final class looper {
	// ...    
	public static void loop() {
		// 获取tls存储的looper对象        
		final looper me = mylooper();
		if (me == null) {
			throw new runtimeexception("no looper; looper.prepare() wasn't called on this thread.");
		}
		final messagequeue queue = me.mqueue;
		// 进入loop主循环方法        
		for (;;) {
			message msg = queue.next();
			// 可能会阻塞,因为next()方法可能会无线循环            
			if (msg == null) {
				// no message indicates that the message queue is quitting.                
				return;
			}
			// this must be in a local variable, in case a ui event sets the logger            
			final printer logging = me.mlogging;
			if (logging != null) {
				logging.println(">>>>> dispatching to " + msg.target + " " +                        
				                                msg.callback + ": " + msg.what);
			}
			// ...            
			final long dispatchstart = needstarttime ? systemclock.uptimemillis() : 0;
			final long dispatchend;
			try {
				// 获取msg的目标handler,然后分发message                
				msg.target.dispatchmessage(msg);
				dispatchend = needendtime ? systemclock.uptimemillis() : 0;
			}
			finally {
				if (tracetag != 0) {
					trace.traceend(tracetag);
				}
			}
			// ...            
			msg.recycleunchecked();
		}
	}
}

handler

创建handler:

public class handler {
	// ...    
	public handler() {
		this(null, false);
	}
	public handler(callback callback, boolean async) {
		// ...        
		// 必须先执行looper.prepare(),才能获取looper对象,否则为null        
		mlooper = looper.mylooper();
		if (mlooper == null) {
			throw new runtimeexception(                
			      "can't create handler inside thread " + thread.currentthread()                        
			      + " that has not called looper.prepare()");
		}
		mqueue = mlooper.mqueue;
		// 消息队列,来自looper对象        
		mcallback = callback;
		// 回调方法        
		masynchronous = async;
		// 设置消息是否为异步处理方式
	}
}

发送消息

子线程通过handler的post()方法或send()方法发送消息,最终都是调用 sendmessageattime()方法。

post方法:

public final boolean post(runnable r){
	return sendmessagedelayed(getpostmessage(r), 0);
}
public final boolean postattime(runnable r, long uptimemillis){
	return sendmessageattime(getpostmessage(r), uptimemillis);
}
public final boolean postattime(runnable r, object token, long uptimemillis){
	return sendmessageattime(getpostmessage(r, token), uptimemillis);
}
public final boolean postdelayed(runnable r, long delaymillis){
	return sendmessagedelayed(getpostmessage(r), delaymillis);
}
private static message getpostmessage(runnable r) {
	message m = message.obtain();
	m.callback = r;
	return m;
}
 

send方法:

public final boolean sendmessage(message msg){
	return sendmessagedelayed(msg, 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 sendemptymessageattime(int what, long uptimemillis) {
	message msg = message.obtain();
	msg.what = what;
	return sendmessageattime(msg, uptimemillis);
}
public final boolean sendmessagedelayed(message msg, long delaymillis){
	if (delaymillis < 0) {
		delaymillis = 0;
	}
	return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);
}
sendmessageattime()
public boolean sendmessageattime(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(messagequeue queue, message msg, long uptimemillis) {
	msg.target = this;
	if (masynchronous) {
		msg.setasynchronous(true);
	}
	return queue.enqueuemessage(msg, uptimemillis);
}

分发消息

在loop()方法中,获取到下一条消息后,执行 msg.target.dispatchmessage(msg),来分发消息到目标handler。

public class handler {
	// ...    
	public void dispatchmessage(message msg) {
		if (msg.callback != null) {
			// 当message存在回调方法,调用该回调方法            
			handlecallback(msg);
		} else {
			if (mcallback != null) {
				// 当handler存在callback成员变量时,回调其handlemessage()方法                
				if (mcallback.handlemessage(msg)) {
					return;
				}
			}
			// handler自身的回调方法            
			handlemessage(msg);
		}
	}
	private static void handlecallback(message message) {
		message.callback.run();
	}
}

总结

Android消息机制Handler深入理解

到此这篇关于深入理解android消息机制handler的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。