android源码解析(6)--HandlerThread分析及使用对比

昨天面试被问到handlerthread了,然后居然不知道,瞬间觉得技术很次啊,回来恶补一下,记录一下,
一。如何使用
public class HandlerThreadActivity extends Activity {
    /**
     * 创建一个HandlerThread
     */
    private HandlerThread mTestHandlerThread;
    /**
     * 处理测试handlerThread中的具体工作的Handler
     */
    private Handler mWorkHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建并启动
        mTestHandlerThread=new HandlerThread("测试用例");
        mTestHandlerThread.start();
        //具体工作在这里处理
        mWorkHandler=new Handler(mTestHandlerThread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what){
                    case 1:
                        SystemClock.sleep(3000);
                        Log.e("TAG", "handleMessage: "+Thread.currentThread().getName());
                        mUiHandler.sendEmptyMessage(0);
                        break;
                }
            }
        };

        mWorkHandler.sendEmptyMessage(1);
    }

    /**
     * 操作UI线程中的工作
     */
    private Handler mUiHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 0:
                    Log.e("TAG", "handleMessage: "+Thread.currentThread().getName());
                    break;
            }
        }
    };
}
使用还是很简单的,这里就不再多说了,具体分析代码中都有注解。

二。源码分析
打开源码才发现,原来很简单,就两百多行代码,其实就是对thread的一个封装。
1)从构造器开始吧:
    //第一个构造器,调用父类构造器,设置线程优先级、名称
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    /**
     * 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;
    }
2)start方法开始,就是调用run方法:
    @Override
    public void run() {
        mTid = Process.myTid();
        //初始化looper
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        //外置一个looper准备好的方法,我们可以做一些想做的事
        onLooperPrepared();
        //looper开始循环
        Looper.loop();
        mTid = -1;
    }
 好像看了半天也没做什么事是吧,这里其实就是要重点理解looper和这个线程绑定了,以后的操作都
 是在这个线程中执行了,如果不懂就先看看前文handler消息机制分析吧,再回过头来看看就发现没什么了
3)其他方法
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason is isAlive() returns false, this method will return null. If this thread 
     * has been started, this method will block until the looper has been initialized.  
     * @return The looper.
     */
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        //这个等待的意思就是说如果你没有调用run方法,我就等着你什么时候调用了再返回
        // If the thread has been started, wait until the looper has been created.
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
    //退出的方法,这个其实就是调用消息队列清空消息,尽量不要用这个方法,下面方法较好
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
    //安全退出,这个方法比较好,但是API要求较高,能用尽量用这个
     public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }
4)结合使用理解
分析了半天源码好像跟什么都没有说一样哈,那就接着使用说吧,上面的mWorkHandler一创建就和使用了这个
线程中的looper,那么处理的消息也肯定是在这个线程了,然后处理完了,又用主线程的handler发送消息
到主线程刷新UI,是不是有点啰嗦呢?反正我觉得有点啰嗦,那有什么好处呢?

三。对比分析
1,直接用Thread:每次使用都去创建,创建和销毁都很耗资源性能的,不好
2.AsyncTask:既然同样都是在分线程处理任务,在主线程更新UI,那么这两个哥们肯定要对比一下了。前文分
  析了asyncTask会创建两个线程池,一个主要管分发任务,一个管处理任务,那么好了,说白了还是就一个线
  程干活呗,不论有多少任务来了,都要先排队,然后一个一个交给那个线程处理,那和HandlerThread好像
  也没有任何区别吧?HandlerThread不就是发过来的工作按照时间进行排序一个一个处理,但是Async中还
  多建了两个线程池、线程池中还建了好几个线程,是不是浪费了?所以我觉得他俩比较HandlerThread完胜。
  这只是比较的asynctask默认情况下的使用。

四。为什么这么设计
其实当我看到这个的时候我就想,使用这么麻烦,干嘛要这么设计,设计灵感来自哪里呢?其实设计灵感就来自主
线程。主线程我们默认会初始化Looper和开启循环,这样我们就可以保证主线程不必要每次都去创建了,节省很
大的开支,同理我们自己也弄一个类似于主线程的分线程多好,用的时候就可以像分线程一样使用,不用了就让
他自己在那待着也不会销毁,这样岂不是不用每次都去创建了也?所以说这个设计思路非常好,当然也优缺点,
就是所有的任务都只能排队进行,不能同时进行,这样当然也避免了并发问题。

五。源码中的使用实例IntentService
昨天写到这里面试去了就,今天继续补上。IntentService就是使用的HandlerThread实现的,那么怎么实现
的呢?我们看看源码就知道了,很简单其实。
1)先看看如何使用:
public class TestIntentService extends IntentService {
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * 给分线程设置一个名字标记,目的就是为了调试的时候使用
     */
    public TestIntentService() {
        super("测试");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //处理耗时操作
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //老规矩这里释放掉一些资源
    }
}
很简单,继承IntentService然后只需要重写onHandleIntent方法,在方法里做耗时的操作就可以了,然后我
们只需要向正常的service一样调用就可以了:
Intent intent=new Intent(this,TestIntentService.class);
//intent里面可以携带一些少量的数据
startService(intent);
2)源码分析
先看看创建的时候调用的oncreate方法都做了什么:
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        //创建HandlerThread并启动
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        //创建处理工作的Handler
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    //分线程中处理工作的Handler
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //对外暴露具体处理工作的方法交给我们去实现
            onHandleIntent((Intent)msg.obj);
            //结束自己?
            stopSelf(msg.arg1);
        }
    }
我们可以看到,一启动服务就创建了一个HandlerThread然后创建一个处理分线程任务的Handler,这里主要看
上面我打了一个问号,想想为什么要打问号?待会我再分析。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值