C语言handler类作用,Handler机制浅析

本文我们主要是要介绍Handler机制,但是涉及到Handler又不得不介绍Message,MessageQueue,Looper,Handler机制主要是依赖后面几个的,所以我们在文中会一次介绍到他们几个。

通过本文你可能会了解到一下几点

1.Handler机制及Handler与Message,MessageQueue,Looper的关系

2.Handler在子线程中的应用及原理

3.Message的复用机制

4.为什么主线程可以有死循环(loop())

Handler源码位置:

android\frameworks\base\core\java\android\os\Handler.java

首先看他的构造:

public Handler() {

this(null, false);

}

public Handler(Callback callback) {

this(callback, false);

}

public Handler(Looper looper) {

this(looper, null, false);

}

public Handler(Looper looper, Callback callback) {

this(looper, callback, false);

}

public Handler(boolean async) {

this(null, async);

}

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;

}

public Handler(Looper looper, Callback callback, boolean async) {

mLooper = looper;

mQueue = looper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

一般我们都用的是无参的构造。先说一下那个Callback,他是一个接口:

public interface Callback {

public boolean handleMessage(Message msg);

}

这是处理消息的一种手段,一般我们也很少用,因为我们都重写了handleMessage方法,效果一样的,我们主要从无参构造这条线看下去。

在无参构造中,直接调用了参数类型为Callback 和boolean 的构造。这里面他给Looper赋值为Looper.myLooper()。来看一下这个方法:

Looper源码位置:

android\frameworks\base\core\java\android\os\Looper.java

public static @Nullable Looper myLooper() {

return sThreadLocal.get();

}

static final ThreadLocal sThreadLocal = new ThreadLocal();

这个方法实际上就是获取当前线程的looper,ThreadLocal是Java的lang包中的类,他的set方法是在当前线程中保存一个对象,get是从当前线程中取出那个对象。这里存取的就是Looper。但这个Looper在哪存的呢?还是从源码中找答案:

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

}

有些人看到这应该就明白了,这里也给出了另一个问题的答案,为什么在子线程中使用Handler或者Toast时要先调用Looper.prepare()。原来这个方法有一个重要的作用就是给当前线程设置Looper,如果不设置,就是null,当然会有问题。但为什么主线程中不需要呢?

这个问题要从app的创建说起,但具体的app启动流程这里就不详细叙述了,只说明一点,在启动app的进程时,Zygote会通过socket接受AMS的请求,通过反射的方法调用ActivityThread的main方法,ActivityThread也就是一个应用的线程,也就是主线程,我们看一下这个方法:

public static void main(String[] args) {

....

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();

....

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");

}

这里调用了prepareMainLooper方法,它和prepare有什么区别呢?直接看源码:

public static void prepareMainLooper() {

prepare(false);

synchronized (Looper.class) {

if (sMainLooper != null) {

throw new IllegalStateException("The main Looper has already been prepared.");

}

sMainLooper = myLooper();

}

}

可见prepareMainLooper也是调用了prepare,只有参数的差别,一个为false一个为true。这个参数最后用到了Looper的构造上:

private Looper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

在构造上又传给了MessageQueue。这个参数quitAllowed的作用在MessageQueue中很清楚:

android\frameworks\base\core\java\android\os\MessageQueue.java

void quit(boolean safe) {

if (!mQuitAllowed) {

throw new IllegalStateException("Main thread not allowed to quit.");

}

....

}

只在这里用到了上文中的参数quitAllowed,也就是为true时,会报异常,异常也很清楚,就是主线程不允许调用quit退出,这个值只在调用prepareMainLooper方法时为true,我们用的时候都是调用prepare方法,也就是为false。

这里做一个小结,Looper.prepare()最主要的作用是初始化Looper,而Handler是基于Looper,一个线程创建后是没有Looper,主线程也不例外,要想使用Handler就必须初始化,一般线程调用pr

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值