Android Handler 绑定自定义线程之HandlerThread

我们在上篇中看到了,如果在Activity中创建了Handler,会默认绑定到Main Thread,那么我们如何将Handler绑定到自定义的线程中呢,以及会遇到什么问题呢?
    
    
    
    
package com.example.handler_01;
 
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
 
public class MainActivity extends ActionBarActivity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyThread thread = new MyThread("MyThread");
thread.start();
thread.mHandler.sendEmptyMessage(1);
}
class MyThread extends Thread{
public Handler mHandler;
public MyThread(String string) {
super(string);
}
@Override
public void run() {
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
System.out.println("Current Thread : " + String.valueOf(Thread.currentThread()));
}
};
}
}
这个时候我们发现出现了错误“ java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()”,这个错误是不是很熟悉,在前面已经讲过,创建Handler的时候 ,会默认绑定当前线程的Looper,但是我们自定义的Thread没有创建Looper,所以报这个错,那么我们按照前一篇文章所讲述的ActivityThread方式创建Handler看看有什么效果。
    
    
    
    
package com.example.handler_01;
 
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
 
public class MainActivity extends ActionBarActivity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyThread thread = new MyThread("MyThread");
thread.start();
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
thread.mHandler.sendEmptyMessage(1);
}
class MyThread extends Thread{
public Handler mHandler;
public Looper mLooper;
public MyThread(String string) {
super(string);
}
@Override
public void run() {
Looper.prepare();
mLooper = Looper.myLooper();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
System.out.println("Current Thread : " + String.valueOf(Thread.currentThread()));
}
};
Looper.loop();
}
}
 
}
我们发现又报错了,这个是空指针异常
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.sendEmptyMessage(int)' on a null object reference
是不是现在觉得很蛋疼,没关系 ,我们继续,把代码中让Main Thread线程休眠1s,我们居然发现可以了,但是实际中,我们可不能让Main Thread休眠 ,这样太影响用户体验了。

现在我们可以看到自定义一个线程,会有很多的不方便,那么HandlerThread就出现了,解决这些问题了,不要问我为什么,请从源码中了解这个雷锋。
    
    
    
    
package com.example.handler_01;
 
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
 
public class MainActivity extends ActionBarActivity {
private Handler mHandler;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HandlerThread mHandlerThread = new HandlerThread("MyHandlerThread");
mHandlerThread.start();
//把Handler和HandlerThread的Looper进行关联
mHandler = new Handler(mHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
System.out.println("Current Thread : " + Thread.currentThread());
}
};
mHandler.sendEmptyMessage(1);
}
 
}
mHandler=new Handler(mHandlerThread.getLooper())
是Handler的另外一个构造函数,这样就把Handler和一个线程的Looper进行了关联 ,发送消息后,就由这个looper以及相应的message queue分发,最后由Handler处理,只是这个处理在自定义的线程中。
从输出中可以看到,消息的处理是在我们自己定义的线程MyHandlerThread中



你可能感兴趣的:(android,HandlerThrea)