关于HandlerThread的一点认识

最近接触到一个HandlerThread类,看名字很高端大气,以为牛逼哄哄的不行。今天就从源码的角度来揭开它神秘的面纱,看看它到底是个什么玩意儿,做什么用。

先提一下假如我们要在主线程里面创建Handler,当然欧克,按照上一篇文章()讲的直接做就好了。那么在子线程呢?子线程没有现成的Looper对象,我们的MessageQueue怎么跑起来。先来看一下在子线程中如果想组成一个消息队列并更新UI怎么做。

public class MainActivity extends Activity {

   
private static final String TAG = "MainActivity";
    private static final int
MSG_UPDATE = 0x100;
    private
Handler mThreadHandler;
    private
HandlerThread mHandlerThread;
    private
TextView textView;
    private static
Handler mHandler;
     private
MyHandler myHandler;

   
@Override
   
protected void onCreate(BundlesavedInstanceState) {
       
super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
textView = (TextView)findViewById(R.id.tv01);
       
mHandler = new Handler(){
           
@Override
           
public void handleMessage(Message msg) {
               
if(msg.what == MSG_UPDATE){

                   
textView.setText(Html.fromHtml("数字每隔3秒更新:<fontcolor='#ff0000'>" +"<i>"+ (new Random().nextInt(100) + 100)+"</i>" + "</font>"));
                   
myHandler.obtainMessage(MSG_UPDATE).sendToTarget();
               
}
            }
        }
;

        new
MyThread().start();

   
}
   

    private class
MyThread extends Thread{

       
@Override
        
public void run() {


            Looper.prepare()
;
            try
{
                Thread.sleep(
3000);
           
} catch (InterruptedException e){
                e.printStackTrace()
;
           
}
           
myHandler = new MyHandler();
            
myHandler.obtainMessage(MSG_UPDATE).sendToTarget();
           
Looper.loop();
       
}


    }
   
private static class MyHandler extends Handler{
       
@Override
       
public void handleMessage(Message msg) {
           
if(msg.what == MSG_UPDATE){
                Log.i(
TAG, "handleMessage:");
                try
{
                    Thread.sleep(
2000);
               
} catch (InterruptedException e){
                    e.printStackTrace()
;
               
}
               
mHandler.obtainMessage(MSG_UPDATE).sendToTarget();
                this
.obtainMessage(MSG_UPDATE).sendToTarget();
           
}
        }
    }

}

 

实际上我们主要目标是实现在子线程创建Handler,并形成消息循环队列。只是为了和接下来的做对比,所以写了这个一个结构。下面来看看用HandlerThread来实现这样一个过程。

public class MainActivity extends Activity {

   
private static final String TAG = "MainActivity";
    private static final int
MSG_UPDATE = 0x100;
    private
Handler mThreadHandler;
    private
HandlerThread mHandlerThread;
    private
TextView textView;
    private static
Handler mHandler;


   
@Override
   
protected void onCreate(BundlesavedInstanceState) {
       
super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
textView = (TextView)findViewById(R.id.tv01);
       
mHandler = new Handler(){
           
@Override
           
public void handleMessage(Message msg) {
               
if(msg.what == MSG_UPDATE){

                   
textView.setText(Html.fromHtml("数字每隔3秒更新:<fontcolor='#ff0000'>" +"<i>"+ (new Random().nextInt(100) + 100)+"</i>" + "</font>"));
                   
myHandler.obtainMessage(MSG_UPDATE).sendToTarget();
               
}
            }
        }
;

         
initBackThread();
        
mThreadHandler.obtainMessage(MSG_UPDATE).sendToTarget();


   
}


   
private void initBackThread() {
       
mHandlerThread = new HandlerThread("handlerthread");
       
mHandlerThread.start();

       
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
           
@Override
           
public void handleMessage(Message msg) {
                
if (msg.what == MSG_UPDATE) {
                   
try {
                       
// 模拟从网络上获取数据的耗时操作
                       
Thread.sleep(3000);
                   
} catch (InterruptedException e){
                       e.printStackTrace()
;
                    
}
                   
mHandler.post(new Runnable() {
                       
@Override
                       
public void run() {

                           
textView.setText(Html.fromHtml("数字每隔3秒更新:<fontcolor='#ff0000'>" +"<i>"+ (new Random().nextInt(100) + 100)+"</i>" + "</font>"));

                           
mThreadHandler.obtainMessage(MSG_UPDATE).sendToTarget();
                       
}
                    })
;
               
}
            }
        }
;
   
}

 

这样我们就完成了和上面同样的效果,我这里为了方便没有创建Handler子类。只是作为演示。

这样做方便了很多,实际上这个HandlerThread并没有做什么了不起的事情,只是帮我们拿到了子线程的Looper,从而可以在主线程中创建的Handler使用的却是子线程的消息循环。看看源码,

public Looper getLooper() {
   
if (!isAlive()) {
       
return null;
   
}
   
   
// If the thread has beenstarted, wait until the looper has been created.
   
synchronized (this) {
       
while (isAlive() && mLooper == null) {
           
try {
                wait()
;
           
} catch (InterruptedException e){
            }
        }
    }
   
return mLooper;
}

当我们调用HandlerThread::getLooper()方法时,如果Looper对象还没有创建,则线程wait(),当我们调用HandlerThread::start()启动线程时会执行HandlerThrad;run()方法,

@Override
public void run() {
   
mTid = Process.myTid();
   
Looper.prepare();
    synchronized
(this) {
       
mLooper = Looper.myLooper();
       
notifyAll();
   
}
    Process.setThreadPriority(
mPriority);
   
onLooperPrepared();
   
Looper.loop();
   
mTid = -1;
}

而run()方法中调用了Looper.prepare()方法创建了Looper的对象并保存到了ThradLocal中,随后调用notifyAll()方法唤醒正在wait()的线程,while()条件判断Looper对象不为null则跳出循环返回Looper对象。Handler拿到该Looper对象后会使用该Looper的loop()方法控制消息队列完成消息分发。至此,就算是完成了在子线程中定义Handler的操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值