android中handler的基本使用方法以及运行原理。
最近看mars的android重置版第二季的视频关于handler的讲解,让我对于这个以前知道怎么用,却不是很明白原理的组件的理解瞬间加深了无数倍。mars真的讲的很好,视频真的都蛮不错的。下面我写写自己学习到的知识,以及自己的了解。
为什么我们需要一个handler?我想这是一个最重要的问题,也就是说handler的作用到底是什么?handler主要是用于线程间的通信,那么问题又来了,为什么一个app中需要多个线程,而不是只有一个UI主线程就可以了呢?
假如app中只有一个UI主线程,那么,当需要进行网络连接,网络下载这些等待耗时较长的任务时,android系统就会检测到UI主线程长时间没有响应,就会发出一个 application not response的异常警告,简称ANR问题。所以,在UI主线程中,是要与用户实时交互的,不能出现长时间的等待问题。于是,这些任务必须在worker thread中进行。
然而根据android的设定,UI主线程之外的线程,(除了特别的控件,例如progressbar)不能修改UI里的控件的,这样又出现了新的问题,我们在子线程获得的数据,该如何反应的UI上与用户进行交互?这样,就出现了这个巧妙的组件,handler!
那么,handler到底是如何运行的呢?handler对象首先取出一个消息对象,存入到一个消息队列messagequeue中,然后在另外一端,有一个looper对象,循环的从消息队列中取出消息对象再交给handler去处理。
public class MainActivity extends ActionBarActivity {
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.cancleButton);
// 点击button启动新线程
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Thread thread = new Mythread();
thread.start();
}
});
handler = new Myhandler();
}
// 复写hanlder中的handlerMessage方法,处理从消息队列中得到的消息
class Myhandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String s = msg.obj.toString();
System.out.println("在当前线程中"+Thread.currentThread().getName()+"获得来自这个线程的消息"+s);
}
}
// 在worker thread中使用handler.obtainMessage()方法得到一个Message对象,再把消息存入message中,发入消息队列
class Mythread extends Thread{
@Override
public void run() {
Message msg = handler.obtainMessage();
msg.obj = currentThread().getName();
handler.sendMessage(msg);
}
}
}
通过这个例子,我们可以看到,handlerMessage()方法是运行在主线程中的,而他可以得到来自worker thread的消息,这样,就可以将消息在UI界面更新了。
为什么只是初始化了一个handler对象,就会自动调用他的handleMessage方法?是因为在android.os.Handler类中有一个looper对象,会循环的从消息队列中取出消息,调用handleM而是撒个方法。
public class MainActivity extends ActionBarActivity {
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.cancleButton);
// 每点击一次button,给worker thread 发送一个消息
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// 在main中使用handler.obtainMessage()方法得到一个Message对象,再把消息存入message中,发入消息队列
Message msg = handler.obtainMessage();
msg.obj = Thread.currentThread().getName();
handler.sendMessage(msg);
}
});
Thread thread = new Mythread();
thread.start();
}
// 复写hanlder中的handlerMessage方法,处理得到的消息
class Myhandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String s = msg.obj.toString();
System.out.println("在当前线程中"+Thread.currentThread().getName()+"获得来自这个线程的消息"+s);
}
}
// work thread 接受这个消息,并调用handleMeesage()方法处理消息
class Mythread extends Thread{
@Override
public void run() {
// looper对象的loop方法从消息队列中取出消息,调用handleMeesage()方法处理消息
Looper.prepare();
handler = new Myhandler();
Looper.loop();
}
}
}
通过运行结果可以知道,handleMessage()方法运行在worker thread中,这样就可以在worker thread中处理来自主线程的消息,实现了进程间的通信。
post方法通过生成一个message,然后把Runnable对象放在message中,再把message放在消息队列中,然后在主线程中取出这个Runnable对象,在主线程中执行。
public class MainActivity extends ActionBarActivity {
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.cancleButton);
// 初始化handler,处理得到的Runnable对象
handler = new Handler();
// 点击按钮执行worker thread
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
Thread thread = new Mythread();
thread.start();
}
});
}
class Mythread extends Thread{
@Override
public void run() {
// 在worker thread 中初始化一个Runnable对象
Runnable runnable = new Runnable() {
public void run() {
// 打印出该Runnable方法执行的线程
System.out.println("当前线程名"+Thread.currentThread().getName());
}
};
// post该Runnable对象
handler.post(runnable);
}
}
}
最后的结果,是这个Runnable对象执行在main线程中。有了post()方法,我们可以直接在worker thread中先生成一个Runnable对象,然后在其中写上更新UI的代码,直接用post方法即可更新UI。
原文地址:http://blog.csdn.net/bigevil/article/details/45648797