HandlerThread 源码 分析

2016/8/20 posted in  Android

HandlerThread

首先文档对这个类的介绍

Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

如果我有一个耗时的任务需要放在非 UI 线程处理,一般情况下是 new 出一个 thread 来执行,然而,这样就存在一个性能问题:多次创建和销毁线程是很耗系统资源的。

为了解这种问题,我们可以自己构建一个循环线程Looper Thread,当有耗时任务投放到该循环线程中时,线程执行耗时任务,执行完之后循环线程处于等待状态,直到下一个新的耗时任务被投放进来。这样一来就避免了多次创建Thread线程导致的性能问题了。其实 Android 系统已经为我们准备了 就是 HandlerThread

HandlerThread使用步骤

//创建实例对象
HandlerThread handlerThread = new HandlerThread("handlerThread");
//启动HandlerThread线程
handlerThread.start();
//构建循环消息处理机制
Handler subHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                //实现自己的消息处理
                return true;
            }
        });

源码分析

public class HandlerThread extends Thread {
    //优先级
    int mPriority;
    int mTid = -1;
    //成员变量里有 Looper,在 run() 中初始化
    Looper mLooper;
 
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }

    @Override
    public void run() {
        mTid = Process.myTid();
        //初始化 looper
        Looper.prepare();
        synchronized (this) {
            //初始化 mLooper
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        //开始循环取消息执行的队列
        Looper.loop();
        mTid = -1;
    }
    

此外还有一些其他的方法

quitSafely()
Looper getLooper()

举个栗子

Android 系统的 IntentService 就是使用了HandlerThread

在 onCreate 方法中

 @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        //新建了工作线程的HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        //由工作线程的HandlerThread 新建出的Handler,其工作队列是在HandlerThread中的线程
        mServiceHandler = new ServiceHandler(mServiceLooper);
        
    }
    
        @Override
    public void onStart(Intent intent, int startId) {
    //与普通的 service 不同的是,我们希望在 service 中行耗时的任务,不想新建 thread 不方便管理。这里任然是主线程,只不过通过发送消息,将耗时的任务放在了 HandlerThread 中
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    
    
     private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
        //我们复写的onHandleIntent()将耗时的操作放在这里onHandleIntent()中
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
    
    
    //在 onDestory 时要销毁队列,不然会内存泄露
        @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }