摘要:本文将带你了解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频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号