观书散遗帙,探古穷至妙。这篇文章主要讲述Android中关于Handler Looper理解相关的知识,希望能为你提供帮助。
在android中每个应用的UI线程是被保护的,不能在UI线程中进行耗时的操作,其他的子线程也不能直接进行UI操作。
为了达到这个目的Android设计了handler Looper这个系统框架。
首先讲解在主线程中使用Handler时源码跟踪过程。
正常在activity的oncreate函数中定义个handler,这种情况下就是默认的主线程的handler,并去复写该类的handleMessage()函数。
private final Handler mMessageHandler = new Handler(){ @Override public void handleMessage(Message msg){ ....; } }
在这里new 了一个Handler类,跟入系统代码
106/** 107* Default constructor associates this handler with the {@link Looper} for the 108* current thread. 109* 110* If this thread does not have a looper, this handler won‘t be able to receive messages 111* so an exception is thrown. 112*/ 113public Handler() { 114this(null, false); 115}
188public Handler(Callback callback, boolean async) { 189if (FIND_POTENTIAL_LEAKS) { 190final Class< ? extends Handler> klass = getClass(); 191if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) & & 192(klass.getModifiers() & Modifier.STATIC) == 0) { 193Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 194klass.getCanonicalName()); 195} 196} 197 198mLooper = Looper.myLooper(); 199if (mLooper == null) { 200throw new RuntimeException( 201"Can‘t create handler inside thread that has not called Looper.prepare()"); 202} 203mQueue = mLooper.mQueue; 204mCallback = callback; 205mAsynchronous = async; 206}
最后需要对mQueue;mCallback;mAsynchronous这三个变量赋值。
这里注意 mLooper = Looper.myLooper(); 对mLooper的初始化。这里进入了Looper类
191public static @Nullable Looper myLooper() { 192return sThreadLocal.get(); 193}
68// sThreadLocal.get() will return null unless you‘ve called prepare(). 69static final ThreadLocal< Looper> sThreadLocal = new ThreadLocal< Looper> ();
92private static void prepare(boolean quitAllowed) { 93if (sThreadLocal.get() != null) { 94throw new RuntimeException("Only one Looper may be created per thread"); 95} 96sThreadLocal.set(new Looper(quitAllowed)); 97} 98
【Android中关于Handler Looper理解】最后new Looper(quitAllowed) 在这里在当前thread中新建了一个Looper对象(所以从这里可以看出来Looper是属于当前thread的)。
正常在我们自己new的线程中都需要调用Looper.prepare(); 语句来为当前线程new一个looper对象。但是对于UI线程中创建的looper是不需要的,因为在初始化UI线程时就已经写好了。
正常UI线程初始化时调用prepareMainLooper这个函数。
99/** 100* Initialize the current thread as a looper, marking it as an 101* application‘s main looper. The main looper for your application 102* is created by the Android environment, so you should never need 103* to call this function yourself.See also: {@link #prepare()} 104*/ 105public static void prepareMainLooper() { 106prepare(false); 107synchronized (Looper.class) { 108if (sMainLooper != null) { 109throw new IllegalStateException("The main Looper has already been prepared."); 110} 111sMainLooper = myLooper(); 112} 113}
对于一般的子线程需要继续调用Looper.loop来启动loop循环进行消息发送。
而同样对于UI线程的looper同样是在初始化过程中已经调用好了。
128public static void loop() { 129final Looper me = myLooper(); 130if (me == null) { 131throw new RuntimeException("No Looper; Looper.prepare() wasn‘t called on this thread."); 132} 133final MessageQueue queue = me.mQueue; .............. 142for (; ; ) { 143Message msg = queue.next(); // might block 144if (msg == null) { 145// No message indicates that the message queue is quitting. 146return; 147} 。。。。。。。。。。 158msg.target.dispatchMessage(msg);
在这个loop()函数中就能真正看到消息循环机制。在一个死循环中for(; ; )不断从queue消息队列中获取messager,如果没有将阻止在该端口等待下一个messager。
在获取一个消息后则放入message中的targe中进行消息分发。
这里的target其实就是最开始在封装一个message进行发送时传入的handler,所以从这里也可以看出,最后消息还是通过handler传入到它所在的线程中调用handleMessage()进行处理。
message.java 的成员变量:
public final class Message implements Parcelable { public int what; public int arg1; public int arg2; public Object obj; public Messenger replyTo; public int sendingUid = -1; /*package*/ static final int FLAG_IN_USE = 1 < < 0; /** If set message is asynchronous */ /*package*/ static final int FLAG_ASYNCHRONOUS = 1 < < 1; /** Flags to clear in the copyFrom method */ /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE; /*package*/ int flags; /*package*/ long when; /*package*/ Bundle data; /*package*/ Handler target /*package*/ Runnable callback; // sometimes we store linked lists of these things /*package*/ Message next;
。。。。
推荐阅读
- 原生APP内置PayPal网页支付方式
- Android 开发第一项目——计算器的开发记录
- Android学习资源网站大全
- Android xUtils3源码解析之注解模块
- Android xUtils3源码解析之数据库模块
- 值得你关注的Android8.0(Android O)上的重要变化
- Google App Engine10年,支持更多你喜欢的编程语言
- Android studio 2.3安装遇到的问题
- PhoneGap 获得APP的VersionName