android 之 Handler 详解----(一)实现的消息传递基本原理(流程分析)
2015-04-25 23:50
549 查看
Handler可以说是android 中必需掌握的一个点,是android 提供的一套完整的消息传递的机制。我们常见的有用于 UI 的更新。
近来对相关的源代码以及使用进行了了解,记录以下几点:
(一)实现的基本原理
(二)常见的使用的基本方式
(三)更新UI的方法
(一)实现的消息传递基本原理(流程分析)
Handler 实现的离不开Looper 以及 MessageQueue,总结来说是:
1.Handler负责消息的发送,Looper负责接收Handler发送的消息,并且直接回传给Handler自己来处理消息。
2.Looper创建的时候会关联一个MessageQueue 的一个存储消息的容器,负责消息的存储。
以下是以main 线程(UI线程)的handler 以及 Looper为例,讲解一下handler消息是如何传递的。
主要的流程如下:
线程创建-----> Looper的创建 ----> handler 与 Looper的关联----->handler 发送消息----->通过Looper以及messageQueue----->回传给自己handler自己处理消息。
下面是详细的流程讲解:
(首先看看以下简单的handler的使用代码)
<例子>
在一个线程中,使用handler 必须要创建相关联的 Looper 来一起使用,不然系统会抛出异常。那为什么在main线程(UI线程)中没有Looper的相关操作呢?其实在main线程(UI线程)在其创建的时候,就已经对looper进行的操作,我们在源代码中查看一下:
<A> . ActivityThread.java中的main函数如下:
主线程在在创建的时候,其中的main方法调用的时候,已经对Looper进行了关联,下面我们跟踪进
入Looper.prepareMainLooper,进入到prepareMainLooper,里面,发现里面有个prepare 方法,以下是prepare()方法的具体代码:
< B > Looper.java
而在 new Looper()中,还创建了一个MessageQueue:
到此为止,UI线程中已经建立了Looper 以及messageQueue了。
在我们的事例代码中,有中new Handler的操作,深入源代码中,查找,里面会发现,里面就是和相应的Looper进行了关联,也关联相关的MessageQueue,Handler中的构造函数:
< C > Handler.java
<例子>中UI线程新建一个handler 的操作,实际也和Looper而进行了关联,然后在oncreate中新建一个线程,通过handler中的sendMessage()方法进行消息的发送操作,下面就开始看看,消息是如何发送回来 handler自身的。
< D >... Handler.java MessageQueue.java
消息已经保存到了MessageQueue中去了,然后Looper的作用就开始了,Looper就是要把MessageQueue中的消息轮询的方式发送出去,
往回看一下 <A> 中的代码,最后的时候,调用了 Looper.loop(),这个作用到底是什么呢?没错,这个就是Looper要传消息了,我们深入看看其中的代码:
<E> Looper.java
上面的代码重点在 轮询 messageQueue里面的message ,然后就是调用msg.target.dispatchMessage(msg), 这个就会发现这个消息回传到了UI线程中的handler了
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
<F> Handler.java
这个时候,消息就重新发回到handler自身的handleMessage 方法中了,消息大功告成的传了回来。
上面是叙述了UI线程中的handler消息的回传的流程,一样的如果我们需要在一个新建的线程中,创建一个handler 来接收其他线程或者UI线程传过来的消息,必须对 Looper进行操作,Looper.prepare()以及Looper.loop()的操作,不然与这个线程不能关联到。UI线程中,只是预先帮我们做了。 当然其实还有另外的方法不用我们自己手动进行,而且可以更加的安全,那个就是HandlerThread,这个后续我关于Handler的使用的帖子,对此进行记录,我的学习状态。
原创,如需转载请标明出处,谢谢~
近来对相关的源代码以及使用进行了了解,记录以下几点:
(一)实现的基本原理
(二)常见的使用的基本方式
(三)更新UI的方法
(一)实现的消息传递基本原理(流程分析)
Handler 实现的离不开Looper 以及 MessageQueue,总结来说是:
1.Handler负责消息的发送,Looper负责接收Handler发送的消息,并且直接回传给Handler自己来处理消息。
2.Looper创建的时候会关联一个MessageQueue 的一个存储消息的容器,负责消息的存储。
以下是以main 线程(UI线程)的handler 以及 Looper为例,讲解一下handler消息是如何传递的。
主要的流程如下:
线程创建-----> Looper的创建 ----> handler 与 Looper的关联----->handler 发送消息----->通过Looper以及messageQueue----->回传给自己handler自己处理消息。
下面是详细的流程讲解:
(首先看看以下简单的handler的使用代码)
<例子>
public class MainActivity extends Activity { //UI线程中的handler处理 private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { if (msg.what == 1) { System.out.println("main thread-----UI thread"); } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //子线程 new Thread(){ @Override public void run() { Message msg = new Message(); msg.what = 1 ; //通过主线程的handler对象,发消息回自己处理 handler.sendMessage(msg); } }.start(); } }
在一个线程中,使用handler 必须要创建相关联的 Looper 来一起使用,不然系统会抛出异常。那为什么在main线程(UI线程)中没有Looper的相关操作呢?其实在main线程(UI线程)在其创建的时候,就已经对looper进行的操作,我们在源代码中查看一下:
<A> . ActivityThread.java中的main函数如下:
Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop();
主线程在在创建的时候,其中的main方法调用的时候,已经对Looper进行了关联,下面我们跟踪进
入Looper.prepareMainLooper,进入到prepareMainLooper,里面,发现里面有个prepare 方法,以下是prepare()方法的具体代码:
< B > Looper.java
public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(); } public static void prepareMainLooper() { prepare(); setMainLooper(myLooper()); myLooper().mQueue.mQuitAllowed = false; } private synchronized static void setMainLooper(Looper looper) { mMainLooper = looper; }在进入looper之中,prepare方法新建了一个 Looper ,然后后面给了mMainLooper,这个时候main线程中的Looper已经准备好了,准备好了,后面就可以使用了。
而在 new Looper()中,还创建了一个MessageQueue:
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
到此为止,UI线程中已经建立了Looper 以及messageQueue了。
在我们的事例代码中,有中new Handler的操作,深入源代码中,查找,里面会发现,里面就是和相应的Looper进行了关联,也关联相关的MessageQueue,Handler中的构造函数:
< C > Handler.java
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 = null;
<例子>中UI线程新建一个handler 的操作,实际也和Looper而进行了关联,然后在oncreate中新建一个线程,通过handler中的sendMessage()方法进行消息的发送操作,下面就开始看看,消息是如何发送回来 handler自身的。
< D >... Handler.java MessageQueue.java
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } 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) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
消息已经保存到了MessageQueue中去了,然后Looper的作用就开始了,Looper就是要把MessageQueue中的消息轮询的方式发送出去,
往回看一下 <A> 中的代码,最后的时候,调用了 Looper.loop(),这个作用到底是什么呢?没错,这个就是Looper要传消息了,我们深入看看其中的代码:
<E> Looper.java
public static void loop(){ Looper me = myLooper(); ... MessageQueue queue = me.mQueue; ... while (true) { Message msg = queue.next(); // might block if (msg != null) { ... msg.target.dispatchMessage(msg); ... msg.recycle(); } } }
上面的代码重点在 轮询 messageQueue里面的message ,然后就是调用msg.target.dispatchMessage(msg), 这个就会发现这个消息回传到了UI线程中的handler了
![](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)
<F> Handler.java
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
这个时候,消息就重新发回到handler自身的handleMessage 方法中了,消息大功告成的传了回来。
上面是叙述了UI线程中的handler消息的回传的流程,一样的如果我们需要在一个新建的线程中,创建一个handler 来接收其他线程或者UI线程传过来的消息,必须对 Looper进行操作,Looper.prepare()以及Looper.loop()的操作,不然与这个线程不能关联到。UI线程中,只是预先帮我们做了。 当然其实还有另外的方法不用我们自己手动进行,而且可以更加的安全,那个就是HandlerThread,这个后续我关于Handler的使用的帖子,对此进行记录,我的学习状态。
原创,如需转载请标明出处,谢谢~
相关文章推荐
- android开发之源码级分析(系统启动流程 & Handler消息机制 & AsyncTask机制)
- Android中Handler传递消息机制详解
- Android异步消息处理机制详解及源码分析 Handler
- Android Handler消息传递机制详解
- 【源码分析】Android消息机制:Handler发出的消息经历了怎样的流程
- 从源码分析Android中Handler的消息传递机制
- Android消息机制之实现两个不同线程之间相互传递数据相互调用
- 源码分析Android消息传递机制
- 消息传递机制的具体实现过程(分析源码之后的总结)
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- Android消息传递之Handler消息机制
- Android消息传递之EventBus 3.0使用详解
- Android Handler消息传递机制,androidhandler
- Android 从源码角度分析消息处理机制(Handler,Looper,Message)
- android的消息处理机制(图+源码分析)——Looper,Handler,Message
- Android 消息传递机制详解
- Android笔记二十五.Android事件Handler消息传递机制
- Android异步消息处理机制详解及源码分析
- Android消息机制Handler的原理详解
- 【源码解读】Handler消息机制流程分析