Handler使用
Handler是android中一个用来处理发送和接受的消息,主要有两个功能:
1)按计划发送消息或执行某个Runnanble(使用POST方法);
2)处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)
使用Handler之前,首先你要清楚两个问题:
第一:当一个android应用程序启动时,系统会开启一个主线程,也就是UI线程,这个主线程负责管理界面中的控件,响应用户的操作。
第二:没有使用另外一个线程启动Handler的时候,Handler是运行在主线程中的,它通过Message对象和子线程进行通信。
既然Handler默认是运行在主线程中的,说明我们同样不能使用handler处理耗时的操作,否则会出现ANR(Application Not Response)现象。
那么什么时候会用到Handler呢
举个例子: 比如我们需要下载一个文件时,这个耗时的操作要放到一个子线程中执行。当文件下载完成后,怎么通知主线程下载完毕呢。
这个时候,我们可以让子线程发送一个消息给Handler,Handler在收到下载完成的消息时,就可以通知主线程更新UI,通知用户下载完成了。
下面给出一个Handler的小例子,它主要演示
功能1: 按计划发送消息或执行某个Runnanble(使用POST方法);
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
* @author abing
*
*/
public class HandlerTest extends Activity {
/** Called when the activity is first created. */
Handler handler = new Handler();
Runnable updateThread = new Runnable() {
@Override
public void run() {
System.out.println("UpdateThread():Thread Id="
+ Thread.currentThread().getId() + " , Thread Name= "
+ Thread.currentThread().getName());
// 延迟3000ms,将需要被执行的线程加入到线程队列中去
handler.postDelayed(updateThread, 3000);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 初始化控件
TextView myTextView = (TextView) findViewById(R.id.myTextView);
Button startButton = (Button) findViewById(R.id.startButton);
Button endButton = (Button) findViewById(R.id.endButton);
startButton.setText("start");
endButton.setText("end");
// 设置监听器
startButton.setOnClickListener(new StartButtonListener());
endButton.setOnClickListener(new EndButtonListener());
}
class StartButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
System.out.println("start click():Thread Id="
+ Thread.currentThread().getId() + " , Thread Name= "
+ Thread.currentThread().getName());
handler.post(updateThread);
}
}
class EndButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
System.out.println("end click():Thread Id="
+ Thread.currentThread().getId() + " , Thread Name= "
+ Thread.currentThread().getName());
handler.removeCallbacks(updateThread);
}
}
}
可以看到,在没有特殊声明的情况下,Handler和Main线程是在同一个线程中,下面给出另一个实例,这个实例演示:
功能2:处理消息队列中从其他线程发送来的消息,避免线程冲突(常见于更新UI线程)
在这个实例中,我们将处理消息队列的Handler放到一个单独的线程中
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
/**
* @author abing
*
*/
public class HandlerTest02 extends Activity {
/** Called when the activity is first created. */
Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 打印当前线程的ID
System.out.println("Activity Thread :"
+ Thread.currentThread().getId());
// 开启一个带有looper的线程类,该类实现了使用looper来处理消息队列的功能,这个类由android提供
HandlerThread handlerThread = new HandlerThread("handler_thread");
handlerThread.start();
MyHandler myHandler = new MyHandler(handlerThread.getLooper());
Message msg = myHandler.obtainMessage();
// 使用bundle对象来传递数据
Bundle b = new Bundle();
b.putInt("age", 20);
b.putString("name", "张三");
msg.setData(b);
// 讲msg发送给目标对象,目标对象就是生成该msg的handler对象
msg.sendToTarget();
} catch (Exception e) {
e.printStackTrace();
System.out.print(e.getMessage());
}
}
/**
* MyHandler类
*
* @author abing
*
*/
class MyHandler extends Handler {
public MyHandler() {
}
/**
* 此函数的意思是将Handler与looper所在的线程绑定 handler会调用looper所在的线程处理消息
*
* @param looper
*/
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
Bundle b = msg.getData();
System.out.println("age is : " + b.getInt("age"));
System.out.println("name is " + b.getString("name"));
System.out.println("Handler Thread;"
+ Thread.currentThread().getId());
}
}
}
运行结果:
可以看到,发送消息的线程为1,处理消息的线程的id为9。这样处理消息队列的线程和主线程就分开了。
转载地址:http://www.67tgb.com/?p=451