Android HandlerThread理解

消息机制中几个重要的类

1、Looper

  • 创建于主线程ActivityThread,内部用threadlocal保存了一个Looper单例对象,因此每个线程中有且仅存在一个Looper对象。
  • 管理MessageQueue,通过Looper.loop()循环获取队列中的任务,并交给handler对象去处理
//ActivityThread的main方法
public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    //在attach方法中会完成Application对象的初始化,然后调用Application的onCreate()方法
    thread.attach(false);
 
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

主线程mainThreadHandler 作用?

2、HandlerThread 

参考:HandlerThread: HandlerThread的理解 - 夜行过客 - 博客园 (cnblogs.com) 

Demo:vpa  XCTaskProcessor

  • 为某个任务/回调单独开一个线程
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

内部重新实例化了一个Looper对象,此looper对象与mainLooper并非同一个,从源码分析

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

通过threadlocal.set保存一个looper,此set对应的key为当前线程

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

通过handlerThread.start开启子线程,在run方法中,通过Looper.prepare(),因此与UIThread的Looper不为同一个。

综上所述,我们可以得出myLooper()和getMainLooper()两者之间的关系:

(1)、在主线程中,myLooper() 等于 getMainLooper()。

(2)、在子线程中,myLooper() 不等于 getMainLooper()。

(3)、一个应用进程中,只有唯一一个getMainLooper(),存在一个或多个myLooper()。

       既然在子线程中myLooper不等于getMainLooper,也就意味着两者维系的MessageQueue也是不相等的。所以我们怎么对Handler进行释放处理的,同样需要关注HandlerThread的释放,不能因为它是个Thread子类就放任不管,除非你能保证它绑定的Handler没有周期性任务,否则我们还是需要执行HandlerThread#quit()/quitSafe()的。

Demo:XCTaskProcessor.java

3、ThreadLocal

 

posted @ 2022-11-09 17:25  随易来了  阅读(69)  评论(0编辑  收藏  举报