昨天面试被问到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.prepare();
synchronized (this ) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
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 ;
}
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 ;
}
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 );
startService(intent);
2)源码分析
先看看创建的时候调用的oncreate方法都做了什么:
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
@Override
public void onCreate () {
super .onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]" );
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
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,这里主要看
上面我打了一个问号,想想为什么要打问号?待会我再分析。