参考http://blog.csdn.net/fesdgasdgasdg/article/details/52081773
- 在异步线程中创建Handler(不带参数的构造方法)需要Looper.prepare( ),但是这个Handler是子线程的(可知Handler在哪个线程执行,就只是哪个线程的,并非所有的Handler都能执行UI操作,它只是一个辅助机制),如下,执行更新UI的操作会崩溃。
new Thread(){
@Override
public void run() {
super.run();
Looper.prepare();
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//子线程UI操作会导致闪退
et.setText("33");
}
};
Looper.loop();
handler.sendEmptyMessage(0);
}
}.start();
在创建Handler对象的过程中,回去获取当前线程的Looper对象,如果当前线程没有掉用过Looper.prepare() 将得到一个运行时错误:
if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); }
当然也可以通过带参数(参数为主线程的Looper)的方式构造Handler,如下,此时这个Handler是运行在主线程的,可以直接更新UI
new Thread(){ @Override public void run() { super.run(); Handler handler = new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); et.setText("33"); } }; handler.sendEmptyMessage(0); } }.start();
Activity中能直接创建Hnadler是因为已经在UI线程里面已经实例化了一个Looper,如下(Looper类准备一个主线程的Looper):
/** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
上面这个方法的调用又是在ActivityThread(应用的主线程就是它)的main方法中,ActivityThread是在启动应用时系统创建的。而且Activity在attach方法中会传过来一个ActivityThread对象,并且使用这个ActivityThread对象赋予当前Activity的ActivityThread对象,至此,主线程的Looper就创建完成了,而这一切是由android系统完成的,我们不需要也不能手动创造主线程的Looper。
一个handler实例可以用来发送和处理message,也可以与一个runnable对象关联.
- 每一个handler只可以与一个looper关联,一个线程最多只能有一个looper,
- 一个looper内置一个唯一的messageQueue。在同一个线程中,你可以再创建一个handler,与同一个looper和messageQueue关联。若多个handler关联同一个looper,则发送的message都会装载同一个messageQueue里面,由同一个looper管理。
- looper抽取出message后,会让message找的妈妈。message是谁发送的,就有谁的handleMessage()方法处理。因为message.target = handler,message持有妈妈的电话号码