Android应用开发之Android源码-Handler分析
白羽 2018-12-19 来源 :网络 阅读 363 评论 0

摘要:本文将带你了解Android应用开发Android源码-Handler分析,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发Android源码-Handler分析,希望本文对大家学Android有所帮助。



        

Handler简介

Handler是Android消息机制的上层接口,多数开发者会使用Handler去更新UI或做延时处理。如下代码所示:


  

new Thread(new Runnable() {

 @Override

 public void run() {

  // do something

  handler.sendMessage(message)

 }

}).start();

   


   

new Handler().postDelayed(new Runnable() {

  @Override

  public void run() {

//do something

  }

 }, 2000);

   

Handler分析

Handler类位于android.os包下,继承Object类

其中可见的构造方法有三个


   

/**

 * Constructor associates this handler with the {@link Looper} for the

 * current thread and takes a callback interface in which you can handle

 * messages.

 *

 * If this thread does not have a looper, this handler won't be able to receive messages

 * so an exception is thrown.

 *

 * @param callback The callback interface in which to handle messages, or null.

 */

public Handler(Callback callback) {

 this(callback, false);

}

 

/**

 * Use the provided {@link Looper} instead of the default one.

 *

 * @param looper The looper, must not be null.

 */

public Handler(Looper looper) {

 this(looper, null, false);

}

 

/**

 * Use the provided {@link Looper} instead of the default one and take a callback

 * interface in which to handle messages.

 *

 * @param looper The looper, must not be null.

 * @param callback The callback interface in which to handle messages, or null.

 */

public Handler(Looper looper, Callback callback) {

 this(looper, callback, false);

}

   

其中Callback是Handler内部定义的接口,只有一个回调方法handleMessage


   

/**

* Callback interface you can use when instantiating a Handler to avoid

* having to implement your own subclass of Handler.

*

* @param msg A {@link android.os.Message Message} object

* @return True if no further handling is desired

*/

  public interface Callback {

public boolean handleMessage(Message msg);

  }

   

这里先来分析无参构造方法


   

public Handler() {

 this(null, false);

}

   

在无参构造方法中调用了重载方法,如下,省略部分代码:



   

/**

  * Use the {@link Looper} for the current thread with the specified callback interface

  * and set whether the handler should be asynchronous.

  *

  * Handlers are synchronous by default unless this constructor is used to make

  * one that is strictly asynchronous.

  *

  * Asynchronous messages represent interrupts or events that do not require global ordering

  * with respect to synchronous messages.  Asynchronous messages are not subject to

  * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.

  *

  * @param callback The callback interface in which to handle messages, or null.

  * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for

  * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.

  *

  * @hide

  */

 public Handler(Callback callback, boolean async) {

  ....//省略

  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;

 }

   

这里需要注意下@hide修饰为隐藏方法,不能直接调用,可以通过反射调用。

这里需要一个Looper对象,如果mLooper属性为空,会抛出异常。如果在主线程(UI线程)中创建Handler对象,默认在主线程中已经调用了Looper.prepareMainLooper()方法,详细代码在ActivityThread类中main方法中。Looper.myLooper()方法会获取当前线程的Looper对象,当当前线程中没有Looper对象时,创建Handler会抛出异常,这就是常见于在子线程中创建Handler之前没有调用Looper.prepare()方法出现的崩溃,有问题代码如下:


   

new Thread(new Runnable() {

 @Override

 public void run() {

  Handler mHandler = new Handler();

 }

}).start();

   

正确在子线程中创建Handler如下:


   

new Thread(new Runnable() {

@Override

public void run() {

 Looper.prepare();

 Handler mHandler = new Handler();

 Looper.loop();

}

  }).start();

   

这里需要注意的是在创建完Handler后,这里又调用了Looper.loop()方法,这个方法是为了在这个线程中运行消息队列。

Looper分析

我们可以查看Looper源码中prepare方法可知,如下:


   

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));

 }

   

当我们调用Looper.prepare方法时,调用重载方法,为当前线程关联一个新的Looper对象,这里使用的是ThreadLocal,有兴趣的可以查看下源码。我们接着看Looper.loop方法:


   

/**

  * Run the message queue in this thread. Be sure to call

  * {@link #quit()} to end the 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;

 

  // Make sure the identity of this thread is that of the local process,

  // and keep track of what that identity token actually is.

&    

   

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程