在Android系统中,当一个应用程序启动时,首先会启动一个主线程(也被称为UI线程),该线程负责管理界面中的UI控件,进行事件分发,并响应用户的操作。在主线程中不能执行比较耗时的操作(一般不能超过5s),否则Android会认为该应用无响应,便会弹出程序没有响应对话框。如果要执行一些像下载、解析大文件等比较耗时的操作的话,则可以放在Service组件中或放在子线程中执行。这时我们又遇到了一个问题,在Android中不允许在子线程中更新UI组件,UI的更新只能在主线程中执行。Android中为我们提供Handler这个类来解决以上的问题。
下面是Handler的详细用法:
1. Handler简介:
Handler在文档中的定义是:Handler主要用来接收子线程发送的数据,并用此数据配合主线程更新UI。
Handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,一旦创建后,系统就会把该实例与一个线程和该线程的消息队列绑定带一起,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处理它们。 当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activities、broadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通过handler来与主线程进行通信。这可以通过在新的线程中调用主线程的handler的post和sendmessage操作来实现。
2. Handler的用途:
1。按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。
2。把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。
3. Handler与线程的关系:
使用Handler的post方法将Runnable对象放到Handler的线程队列中后,该Runnable的执行其实并未单独开启线程,而是仍然在当前Activity线程中执行的,Handler只是调用Runnable对象的run方法。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startButton = (Button)findViewById(R.id.startButton);
endButton = (Button)findViewById(R.id.endButton);
startButton.setOnClickListener(new StartButtonListener());
endButton.setOnClickListener(new EndButtonListener());
}
class StartButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
//Causes the Runnable r to be added to the message queue
handler.post(otherTheard);
}
}
class EndButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
// Remove any pending posts of Runnable r that are in the message queue.
handler.removeCallbacks(otherTheard);
}
}
/**
* Each Handler instance is associated with a single thread and that thread's message queue
* There are two main uses for a Handler:
* (1) to schedule messages and runnables to be executed as some point in the future;
* (2) to enqueue an action to be performed on a different thread than your own.
*/
Handler handler = new Handler();
Runnable otherTheard = new Runnable() {
@Override
public void run() {
System.out.println("other theard");
// TODO Auto-generated method stub
/**
* Causes the Runnable r to be added to the message queue,
* to be run after the specified amount of time elapses.
* The runnable will be run on the thread to which this handler is attached.
*/
handler.postDelayed(otherTheard, 3000);
}
};
上面的程序实现:点击开始按钮时,每个三秒钟打印一次“other thread”,当点击结束按钮的时候停止打印
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startProgressBar = (Button)findViewById(R.id.startProgressButton);
progressBar = (ProgressBar)findViewById(R.id.progressBar);
//当点击进度条按钮时启动一个新的线程
startProgressBar.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
progressBar.setVisibility(View.VISIBLE);
progressBarHandler.post(progressBarThread);
}
});
}
Handler progressBarHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
progressBar.setProgress(msg.arg1);
progressBarHandler.post(progressBarThread);
}
};
//新线程中运行的内容
Runnable progressBarThread = new Runnable() {
int i = 0;
@Override
public void run() {
// TODO Auto-generated method stub
i += 10;
//Returns a new Message from the global message pool.
//More efficient than creating and allocating new instances.
Message msg = handler.obtainMessage();
msg.arg1 = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in handleMessage(Message),
* in the thread attached to this handler.
*/
progressBarHandler.sendMessage(msg);//发送消息
if (i == 100)
progressBarHandler.removeCallbacks(progressBarThread);
}
};
上面的代码实现了,当点击进度条按钮时,出现一个进度条,每隔1秒钟进度条前进10.