handler机制的一个引子android
在android系统当中,有一个很是重要的铁律,在UI线程以外,是不能修改UI的,在后台线程,新起一个线程,获得的数据结果是不能直接反映在UI上的。
MainThread (UI线程或主线程)和 WorkrThread (除了主线程以外的其余的线程都叫workThread,对一些可能产生阻塞的操做要放在workthread中完成)
workthread从原则上来说是不容许操做UI的,个别控件除外(ProgressBar)
在一个应用程序当中,UI线程一般用于接收用户的界面输入以及将运算结果反馈给用户程序员
一个问题,workThread中运算,结果没法反馈到UI,又不能把运算的过程放在主线程中,就产生了workThread和mainThread通信的问题。网络
handle机制就是解决这一问题的ide
什么是handler,handler消息处理机制:oop
handler就是一个消息处理器,handler,looper(循环器),messageQueue 所构成的这样的一个系统,是android系统当中最重要的消息传递,以及消息处理机制。
handler负责把消息对象加入到消息队列当中去,looper(循环器)负责把消息对象从消息队列当中取出。handler负责放,looper负责从消息队列中往外取。
若是消息队列中没有消息对象,那么负责取出消息对象的LOOP的这行代码就会产生阻塞(处于等待的状态),looper把消息对象从消息队列中取出来以后干什么呢?
looper将会调用handler的handlerMessage方法来处理message对象
线程
主线程中 Handler A发了一个消息,Handler B在主线程中能不能接收到这个消息呢?一个handler的实例只能接受到本身发的message的信息,对象
不少handler共享的是一个messageQueue,经过Message 的what的属性来进行标的,只能收到本身handler相关的message队列
主线程有一个Looper,是一个死循环,监听消息队列,但又不是额外的线程,可是不会阻塞主线程,Looper由系统来控制的,底层的vm来控制的消息队列
并不是每一个线程都有Looper的实例string
handler类的主要做用有两个:
在新启动的线程中发送消息,在主线程中获取、处理消息。
每一个线程只拥有一个Looper,loop方法负责读取消息队列中的消息,读到信息以后就把消息交给发送该消息的handler处理
在UI线程中,系统已经初始化了一个Looper对象,所以程序直接建立handler便可,而后经过handler发送处理消息
程序员本身启动的子线程,程序员须要本身建立一个Looper对象,用prepare方法建立looper对象。
示例1(从workThread向mainThread发消息)
public class MainActivity extends Activity {
private TextView textView;
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textviewId);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
handler = new MyHandler();
}
class ButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
Thread thread = new NetWorkThread();
thread.start();
}
}
class NetWorkThread extends Thread {
@Override
public void run() {
try {
Thread.sleep( 2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String string = "从网络测获取的数据";
Message msgMessage = handler.obtainMessage();
msgMessage.obj = string;
//sendmessage方法不管在主线程中仍是workthread中都是能够发送的
handler.sendMessage(msgMessage);
}
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
String string = (String)msg.obj;
//在主线程中就能够随意的操做UI了
textView.setText(string);
}
}
}
示例2(从mainThread向workThread发消息,在workThread中生成handler对象)
public class MainActivity extends Activity {
private Handler handler;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
}
});
WorkerThread wtThread = new WorkerThread();
wtThread.start();
}
class WorkerThread extends Thread {
@Override
public void run() {
//准备Looper对象
Looper.prepare();
//在workThread当中生成一个handler对象
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("收到了消息对象");
}
};
//调用Loop()方法以后,Looper对象不断的从消息队列当中取出消息对象,而后调用handler的handleMessage方法
//处理消息对象,若是消息队列当中没有消息对象,则线程阻塞
Looper.loop();
}
}
LOOPER是由系统控制的,底层实现的,不阻塞主线程
HandlerThread类有Looper对象,不须要prepare}