android 之 Handler 详解----(一)实现的消息传递基本原理(流程分析)
来源:互联网 发布:笔顺查询软件 编辑:程序博客网 时间:2024/05/18 01:55
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的使用代码)
<例子>
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了
<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 详解----(一)实现的消息传递基本原理(流程分析)
- Android Handler类消息传递机制(一)介绍
- Android 的消息机制(Handler消息传递机制)
- android开发之源码级分析(系统启动流程 & Handler消息机制 & AsyncTask机制)
- Handler消息传递机制(一)
- Handler消息(Message)传递机制详解
- Android消息传递之Handler消息机制
- Android消息传递之Handler消息机制
- Android消息传递之Handler消息机制
- 从源码分析Android中Handler的消息传递机制
- Android之Handler详解(一)
- Android之Handler详解(一)
- Android之Handler详解(一)
- Android学习笔记--Handler消息传递机制(Handler实现自动播放动画)
- Android消息处理流程(handler)
- Android中Handler传递消息机制详解
- Android Handler消息传递机制详解
- Android消息传递之Handler的简单用法
- 报名管理系统思想总结
- 避免无聊的讨论
- SPFA算法(Shortest Path Faster Algorithm)最短路径快速算法,队列优化
- 黑马程序员--java--ApI常见对象
- ArrayList, Vector和LinkedList详解
- android 之 Handler 详解----(一)实现的消息传递基本原理(流程分析)
- Log4J使用小总结
- uva 213
- 餐饮管理系统思想总结
- QT打印PDF
- android:Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lcom/ke
- Metric Manager
- Altera FPGA LCD1602液晶显示屏封装
- 都“全民阅读”了你还不装X