(转)收集——Android Handler分析总结篇
来源:互联网 发布:mac 显示已经更新系统 编辑:程序博客网 时间:2024/06/01 10:05
- Handler
- Handler的由来
- handler的作用
- 让线程延时执行
- 让任务在其他线程中执行并返回结果
- Handler原理分析
- Handler的构造函数
- Handle发送消息的几个方法源码
- Looper原理分析
- 首先看prepare方法
- loop方法
- quit
- Handler的dispatchMessage的源码如下
- Looper_handler_thread_message
- 定义
- 关系
- 线程的魔法师 Looper
- MessageQueue
- Message
- Handler
- 如何在子线程中使用Handler
- Android Handler内存泄露分析
- 切断handler和msg的联系
- 切断handler和外部类的引用
- 子线程更新UI的几种方式
- Viewpost
- runOnUiThread
- 不使用Handler真的不能更新UI吗研究但不推荐
- 总结
- 参考链接
- Handler
Handler
Handler的由来
当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程。
Android的UI操作并不是线程安全的(出于性能优化考虑),意味着如果多个线程并发操作UI线程,可能导致线程安全问题。
为了解决Android应用多线程问题—Android平台只允许UI线程修改Activity里的UI组建,就会导致新启动的线程无法改变界面组建的属性值。
简单的说:当主线程队列处理一个消息超过5秒,android 就会抛出一个 ANR(无响应)的异常,所以,我们需要把一些要处理比较长的消息,放在一个单独线程里面处理,把处理以后的结果,返回给主线程运行,就需要用的Handler来进行线程建的通信。
handler的作用
让线程延时执行
两个主要方法:
final boolean postAtTime(Runnable r, long uptimeMillis)final boolean postDelayed(Runnable r, long delayMillis)
让任务在其他线程中执行并返回结果
分为两个步骤:
在新启动的线程中发送消息
使用Handler对象的sendMessage()方法或者SendEmptyMessage()方法发送消息。
在主线程中获取处理消息
重写Handler类中处理消息的方法(void handleMessage(Message msg)),当新启动的线程发送消息时,消息发送到与之关联的MessageQueue。而Hanlder不断地从MessageQueue中获取并处理消息。
Handler原理分析
Handler的构造函数
public Handler() public Handler(Callbackcallback) public Handler(Looperlooper) public Handler(Looperlooper, Callbackcallback)
(1)第①个和第②个构造函数都没有传递Looper,这两个构造函数都将通过调用Looper.myLooper()获取当前线程绑定的Looper对象,然后将该Looper对象保存到名为mLooper的成员字段中。
下面来看①②个函数源码:
public Handler() { this(null, false);}public Handler(Callback callback) { this(callback, false);}//他们会调用Handler的内部构造方法public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() ||klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } }/************************************ mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
通过Looper.myLooper()获取了当前线程保存的Looper实例,又通过这个Looper实例获取了其中保存的MessageQueue(消息队列)。每个Handler 对应一个Looper对象,产生一个MessageQueue 。
(2)第③个和第④个构造函数传递了Looper对象,这两个构造函数会将该Looper保存到名为mLooper的成员字段中。
下面来看③④个函数源码:
public Handler(Looper looper) { this(looper, null, false);} public Handler(Looper looper, Callback callback) { this(looper, callback, false);}//他们会调用Handler的内部构造方法public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}
(3)第②个和第④个构造函数还传递了Callback对象,Callback是Handler中的内部接口,需要实现其内部的handleMessage方法,Callback代码如下:
public interface Callback { public boolean More ...handleMessage(Message msg);}
Handler.Callback是用来处理Message的一种手段,如果没有传递该参数,那么就应该重写Handler的handleMessage方法,也就是说为了使得Handler能够处理Message,我们有两种办法:
1. 向Hanlder的构造函数传入一个Handler.Callback对象,并实现Handler.Callback的handleMessage方法
2. 无需向Hanlder的构造函数传入Handler.Callback对象,但是需要重写Handler本身的handleMessage方法
也就是说无论哪种方式,我们都得通过某种方式实现handleMessage方法,这点与Java中对Thread的设计有异曲同工之处。
Handle发送消息的几个方法源码
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); } public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); } 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); }
可以看出他们最后都调用了sendMessageAtTime(),然后返回了enqueueMessage方法,下面看一下此方法源码:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { //把当前的handler作为msg的target属性 msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
queue.enqueueMessage :
变量queue表示的是Handler所绑定的消息队列MessageQueue,通过调用queue.enqueueMessage(msg, uptimeMillis)我们将Message放入到消息队列中。
Looper原理分析
我们一般在主线程申明Handler,有时我们需要继承Thread类实现自己的线程功能,当我们在里面申明Handler的时候会报错。其原因是主线程中已经实现了两个重要的Looper方法,下面看一看ActivityThread.java中main方法的源码:
public static void main(String[] args) { //......省略 Looper.prepareMainLooper();//> ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } AsyncTask.init(); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop();//> throw new RuntimeException("Main thread loop unexpectedly exited");}
首先看prepare()方法
public static void prepare() { prepare(true);}private static void prepare(boolean quitAllowed) { //证了一个线程中只有一个Looper实例 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));}
该方法会调用Looper构造函数同时实例化出MessageQueue和当前thread.
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();} public static MessageQueue myQueue() { return myLooper().mQueue;}
prepare()方法中通过ThreadLocal对象实现Looper实例与线程的绑定。
loop()方法
public static void loop() { 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; Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); for (;;) { Message msg = queue.next(); // might block if (msg == null) { return; } Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); }//重点**** msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // 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.recycleUnchecked(); }}
首先looper对象不能为空,就是说loop()方法调用必须在prepare()方法的后面。
Looper一直在不断的从消息队列中通过MessageQueue的next方法获取Message,然后通过代码msg.target.dispatchMessage(msg)让该msg所绑定的Handler(Message.target)执行dispatchMessage方法以实现对Message的处理。
注:写在Looper.loop()之后的代码不会被立即执行,当调用后 mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。Looper对象通过MessageQueue 来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
quit()
public void quit() { Message msg = Message.obtain(); // NOTE: By enqueueing directly into the message queue, the // message is left with a null target. This is how we know it is // a quit message. mQueue.enqueueMessage(msg, 0);}
Handler的dispatchMessage的源码如下:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
可以看到Handler提供了三种途径处理Message,而且处理有前后优先级之分:首先尝试让postXXX中传递的Runnable执行,其次尝试让Handler构造函数中传入的Callback的handleMessage方法处理,最后才是让Handler自身的handleMessage方法处理Message。
Looper_handler_thread_message
定义
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
Android 系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
关系
Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。Message Queue(消息队列),MQ被封装到Looper里面了,我们不会直接与MQ打交道。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
这样说来,多个Handler都可以共享同一Looper和MessageQueue了。当然,这些Handler也就运行在同一个线程里。
线程的魔法师 Looper
是MessageQueue的管理者。每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的。同时每一个Looper对象和一个线程关联。通过调用Looper.myLooper()可以获得当前线程的Looper对象创建一个Looper对象时,会同时创建一个MessageQueue对象。除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义 一个Looper对象(通过prepare函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了。Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理。处理完成后,调用Message.recycle()将其放入Message Pool中。
Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。使用Looper类创建Looper线程很简单:
public class LooperThread extends Thread { @Override public void run() { // 将当前线程初始化为Looper线程 Looper.prepare(); // ...其他处理,如实例化handler // 开始循环处理消息队列 Looper.loop(); }}
通过上面两行核心代码,你的线程就升级为Looper线程了!!!
MessageQueue
是一种 数据 结构,见名知义,就是一个消息队列,存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。创建一个线程的时候,并不会自动 创建其MessageQueue。通常使用一个Looper对象对该线程的MessageQueue进行管理。主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个Message Queue。其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare函数来实现。
Message:
消息对象,Message Queue中的存放的对象。一个Message Queue中包含多个Message。 Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从Message Pool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果Message Pool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从Message Queue中删除,同时放入到Message Pool中。除了上面这种方式,也可以通过Handler对象的obtainMessage()获取 一个Message实例。
Handler
消息的处理者,handler 负责将需要传递的信息封装成Message,通过调用handler 对象的obtainMessage()来实现;将消息传递给Looper,这是通过handler 对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该handler 对象收到该消息后,调用相应的handler 对象的handleMessage()方法对其进行处理。
如何在子线程中使用Handler
Handler本质是从当前的线程中获取到Looper来监听和操作MessageQueue,当其他线程执行完成后回调当前线程。
子线程需要先prepare()才能获取到Looper的,是因为在子线程只是一个普通的线程,其ThreadLoacl中没有设置过Looper,所以会抛出异常,而在Looper的prepare()方法中sThreadLocal.set(new Looper())是设置了Looper的。
class Rub implements Runnable { public Handler myHandler; // 实现Runnable接口的线程体 @Override public void run() { /*①、调用Looper的prepare()方法为当前线程创建Looper对象并, 创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue*/ Looper.prepare(); /*.②、创建Handler子类的实例,重写HandleMessage()方法,该方法处理除当前线程以外线程的消息*/ myHandler = new Handler() { @Override public void handleMessage(Message msg) { String ms = ""; if (msg.what == 0x777) { } } }; //③、调用Looper的loop()方法来启动Looper让消息队列转动起来 Looper.loop(); } }
注意分成三步:
1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
2.有了Looper之后,创建Handler子类实例,重写HanderMessage()方法,该方法负责处理来自于其他线程的消息。
3.调用Looper的looper()方法启动Looper。
然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。
更好一点的示例参考:
public class MainActivity extends Activity { private LooperThread looperThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); looperThread = new LooperThread(); looperThread.start(); looperThread.getHandler().sendEmptyMessage(1); } class LooperThread extends Thread { private Handler mHandler; private final Object mLock = new Object(); public void run() { Looper.prepare(); synchronized (mLock) { mHandler = new Handler(){ @Override public void handleMessage(Message msg) { ..... } }; mLock.notifyAll(); } Looper.loop(); } public Handler getHandler() { synchronized (mLock) { if (mHandler == null) { try { mLock.wait(); } catch (InterruptedException e) { } } return mHandler; } } public void exit() { getHandler().post(new Runnable(){ public void run() { Looper.myLooper().quit(); }}); } } }
Android Handler内存泄露分析
This Handler class should be static or leaks might occur。
这个警告的产生是由于将Handler声明为了非静态内部类(匿名或非匿名),这种情况下可能会产生内存泄露,导致Activity无法释放。
我们使用Handler post一个Message时,Message会在主线程的MessageQueue中排队。由于消息处理中需要调用Message对应Handler的回调,Message会持有Handler的引用。当Handler为非静态内部类(匿名或非匿名)时,Handler就会持有外部类的引用,如果外部类是Activity,这个Activity对象有可能会泄露,尤其是通过调用Handler的postDelayed()方法发送消息,Message会长时间在MessageQueue中存在,泄露的可能性将更大。
要解决这个问题,需要做的就是想办法切断这个引用关系链(Message -> Handler -> Activity),要么切断Message -> Handler的引用,要么切断Handler -> Activity的引用。
切断handler和msg的联系
处理方法是在使用Handler的组件生命周期结束前清除掉MessageQueue中的Message对象(比如,在Activity的onDestroy()中调用Handler的remove*方法)。Handler主要有下面一些方法来清楚Message对象:
比如:handler启动runnable,延迟启动作用等。
private Handler handler = new Handler();private Runnable runnable = new Runnable(){ public void run(){ update(); handler.postDelayed(runnable.this,1000); }};handler.postDelayed(runnable,1000); //开始timerhandler.removeCallbacks(runnable); //停止Timerps:当然runnable也可以用Implements的方式.
removeCallbacks(Runnable r) ——清除r匹配上的Message。removeCallbacks(Runnable r, Object token) ——清除r匹配且匹配token(Message.obj)的Message,token为空时,只匹配r。removeCallbacksAndMessages(Object token) ——清除token匹配上的Message。removeMessages(int what) ——按what来匹配removeMessages(int what, Object object) ——按what来匹配我们需要的是清除以该Handler为target的所有Message(包括Callback),那么调用如下方法即可handler.removeCallbacksAndMessages(null);
切断handler和外部类的引用
可以将Handler声明为静态内部类,避免对外部类的强引用,如果在Handler的内部方法中需要引用外部类,可以在其内部声明一个WeakReference引用外部类的实例。
public class MyActivity extends Activity{ MyHandler myHandler = new MyHandler(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onDestroy() { super.onDestroy(); myHandler.removeCallbacksAndMessages(null); } private static class MyHandler extends Handler{ private WeakReference<MyActivity> activity; MyHandler(MyActivity ac) { activity = new WeakReference<MyActivity>(ac); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //do something if (activity != null) { MyActivity myActivity = activity.get(); //...... } } }; }
子线程更新UI的几种方式
Handler.post(Runnable)Handler.sendMessage()View.post(Runnable)AsyncTaskActivity.runOnUiThread()
这几种方式看起来差别很大,但实际上它们的原理都是相同的,最终都是通过Handler的sendMessage方法来发送消息,然后在UI线程中处理Handler的回调。只是Google帮我们对Handler机制进行了不同程度的封装以适应不同的应用场景。
View.post()
public boolean post(Runnable action) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { return attachInfo.mHandler.post(action); } // Assume that post will succeed later ViewRootImpl.getRunQueue().post(action); return true; }
方法中调用了attachInfo.mHandler.post(action)去发送消息,其实就是调用了Handler的post()方法,继续看这个方法:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
post方法里使用的就是sendMessge()的方式发送消息。
runOnUiThread()
public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action); } else { action.run(); } }
首先判断是否是主线程,如果是就直接执行代码逻辑,如果不是,依然是调用了Handler 的post()方法。从这里可以看出,所有可以实现子线程更新UI的方法的原理都是一样的。
不使用Handler真的不能更新UI吗?(研究,但不推荐)
new Thread(new Runnable() { @Override public void run() { btn.setText("aaaaaaaaa"); } }).start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } btn.setText("cccccccc"); } }).start();
这段代码在Activity的onCreate回调中执行,btn是我们定义的一个Button对象。从执行结果看,第一段代码顺利执行且UI正确更新,却在执行第二段代码的时候发生了崩溃,这是为什么呢?
异常: Only the original thread that created a view hierarchy can touch its views.
根据堆栈信息,更新UI时会调用View的invalidate()方法,继而调用ViewRootImpl的invalidateChildInParent()方法,其中调用了checkThread(),其中会检查当前是否为主线程,否则抛出上面的那个异常。
public ViewParent invalidateChildInParent(int[] location, Rect dirty) { checkThread(); if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty); if (dirty == null) { invalidate(); return null; } else if (dirty.isEmpty() && !mIsAnimating) { return null; }......}
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }
也就是说是在ViewRootImpl这个类中进行了线程的检查。只是在onCreate()中更新UI的时候,ViewRootImpl的对象还没有创建,因此不会进行这个检查,也就出现了上面例子中的现象。那么它是在什么时候创建的呢?
ActivityThread类会调用handleResumeActivity方法将顶层视图DecorView添加到PhoneWindow中,我们就从handleResumeActivity开始看起。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { .................. if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); //得当当前Activity的WindowManagerImpl对象 ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l); .....................
代码中,ViewManager wm = a.getWindowManager()这个得到的是一个WindowManagerImpl类的对象,然后调用了WindowManagerImpl类的addView方法。查看addView方法,又调用了mGlobal的addView方法,mGlobal是WindowManagerGlobal类的对象。
@Override public void addView(View view, ViewGroup.LayoutParams params) { mGlobal.addView(view, params, mDisplay, mParentWindow); }
然后看WindowManagerGlobal类的addView方法:
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ............ ViewRootImpl root; ............ root = new ViewRootImpl(view.getContext(), display); ........... // do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { ........... } }
终于看到了ViewRootImpl,它正式在这里创建的。也就是说,ViewRootImpl是在onResume执行之后创建的。这也就解释了为什么直接在Activity的onCreate中在子线程更新UI不会报错,而在延时一段时间后却出现崩溃。
总结
主线程中,系统已经初始化了一个Looper对象,因此可以直接创建Handler即可,就可以通过Handler来发送消息、处理消息。 程序自己启动的子线程,程序必须自己创建一个Looper对象,并启动它,调用Looper.prepare()方法。
prapare()方法:保证每个线程最多只有一个Looper对象。(因为初始创建第一个Looper的时候会设置成ThreadLocal,然后后面要是再次创建会判断,抛出异常)。
looper()方法:启动Looper,使用一个死循环不断取出MessageQueue中的消息,并将取出的消息分给对应的Handler进行处理。
MessageQueue:由Looper负责管理,它采用先进先出的方式来管理Message。
Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
参考链接
http://www.cnblogs.com/codingmyworld/archive/2011/09/14/2174255.html
http://blog.sina.com.cn/s/blog_5da93c8f0100y4ul.html
http://blog.csdn.net/amazing7/article/details/51424038
http://blog.csdn.net/goodlixueyong/article/details/50831958
- (转)收集——Android Handler分析总结篇
- android源码分析——Handler
- android学习日志—Handler源码分析
- Android 内存泄漏案例分析总结(Handler)
- Android 内存泄漏案例分析总结(Handler)
- Android学习总结(3)——Handler深入详解
- Android 点滴——Handler用法总结
- ANDROID的HANDLER总结(转)
- Android的Handler总结(转)
- (转)android的消息处理机制(图+源码分析)——Looper,Handler,Message
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- [转]Android的Handler总结
- 每日一得--hadoop学习笔记
- Behavioral Patterns Part 3/11: Interpreter Pattern
- 174、请简述以下两个for循环的优缺点(5分)
- 浅析nodejs实现Websocket的数据接收与发送
- mysql进阶:find_in_set的使用例子
- (转)收集——Android Handler分析总结篇
- Array数组对象常用操作总结(一)
- 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)
- Kafka笔记-1-kafka入门介绍
- Git常用命令总结
- 【GitHub】README.MD 编写
- 面试的心情
- Android Studio 安装
- Android 已经提供DisplayMetircs 类可以很方便的获取分辨率