5-1 自定义与线程相关的Handler
1.在线程中通过Looper.prepare()方法创建一个与线程相关的Looper对象;
2. 在线程中通过Handler的new关键字,创建一个Handler对象,这个对象在创建的时候会关联上1中创建的Looper对象
3. 调用Looper对象的loop()方法去轮询它的MessageQueue
4. 通过其他的线程拿到这个线程的Handler对象之后调用sendMessage()之后,在这个线程中就可以进行Message的处理了。
我们一般是在主线程中创建Handler对象,在主线程中处理Message,在子线程中调用这个Handler对象的sendMessage()来发送message。所以Handler是在哪个线程创建就有哪个线程处理Message和轮询,而由别的线程负责给这个Handler发送Message。
1.注意:在主线程中创建的Handler的handleMessage()方法不要写耗时的操作,否则会导致UI卡死,因为这个handleMessage()方法是在UI线程中调用的。
package com.example.yzx;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;
public class SecondActivity extends Activity {
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
System.out.println("UI---------" + Thread.currentThread());
};
};
class MyThread extends Thread {
public Handler handler;
@Override
public void run() {
// TODO Auto-generated method stub
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("currentThead:" + Thread.currentThread());
}
};
Looper.loop();
}
}
private MyThread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setText("hellow Handler");
setContentView(textView);
thread = new MyThread();
thread.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
thread.handler.sendEmptyMessage(1);
handler.sendEmptyMessage(1);
}
}
5-2 HanlderThread是什么 (11:51)
HandlerThread避免多线程导致空指针问题。
handlerthread 默认【创建一个looper然后和一handler关联,那么所有的handleMessage方法是在一个子线程中进行,可以用handlerthread模拟一个异步任务,将主线程的任务发送个子线程,处理一些比较耗时操作
-----------------------------------------------------------------------------------------
1.一个Handler的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler之前先初始化线程的消息队列
2.HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量。这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是 消息队列+消息循环。
在其run()方法中,调用Looper.myLooper()获得一个looper对象。
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
在创建handler时使用getLooper()方法,其实现其实是一直等待looper对象的获得。
while (isAlive() && mLooper == null) {
try {
wait();
}
}
3.Handler在创建的时候可以指定Looper,这样通过Handler的sendMessage()方法发送出去的消息就会添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情况下,Handler绑定的是创建它的线程的Looper。如果这个线程的Looper不存在,程序将抛出"Can't create handler inside thread that has not called Looper.prepare()"。
- 创建Handler的时指定的looper,可以是别的线程创建的。所以Handler中MessageQueue的轮询不一定非要是创建Handler的线程进行,还可以在别的线程中进行。
这个时候我们就需要使用HandlerThread这个类来创建这个Looper了,这样消息的处理就在新创建的HandlerThread中进行。(如图)
mThread = new HandlerThread("Handler Thread");
mHandler = new Handler(mThread.getLooper()){
public void handleMessage(android.os.Message msg) {
... };
};
两个线程切换的过程中,looper没有创建 会抛出控制异常
handlerThread用来避免这个异常
package com.example.yzx;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.widget.TextView;
public class threeActivity extends Activity {
private TextView text;
private HandlerThread thread;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
text = new TextView(this);
text.setText("handler Thread");
setContentView(text);
thread = new HandlerThread("handler thread");
thread.start();
handler = new Handler(thread.getLooper()) {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
System.out.println("current thread---------->" + Thread.currentThread());
}
};
handler.sendEmptyMessage(1);
}
}