对于Handler,先看看sdk doc对它的描述:/docs/reference/android/os/Handler.html
A Handler allows you to send and process and Runnable
objects associated with a thread's . Each Handler
instance is associated with a single thread and that thread's message
queue. When you create a new Handler, it is bound to the thread /
message queue of the thread that is creating it -- from that point on,
it will deliver messages and runnables to that message queue and execute
them as they come out of the 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; and (2) to enqueue
an action to be performed on a different thread than your own.
Scheduling messages is accomplished with the , , , , , , and methods. The post versions allow
you to enqueue Runnable objects to be called by the message queue when
they are received; the sendMessage versions allow you to enqueue
a object containing a bundle of data that will be
processed by the Handler's method (requiring that
you implement a subclass of Handler).
When posting or sending to a Handler, you can either
allow the item to be processed as soon as the message queue is ready
to do so, or specify a delay before it gets processed or absolute time for
it to be processed. The latter two allow you to implement timeouts,
ticks, and other timing-based behavior.
When a
process is created for your application, its main thread is dedicated to
running a message queue that takes care of managing the top-level
application objects (activities, broadcast receivers, etc) and any windows
they create. You can create your own threads, and communicate back with
the main application thread through a Handler. This is done by calling
the same post or sendMessage methods as before, but from
your new thread. The given Runnable or Message will then be scheduled
in the Handler's message queue and processed when appropriate.
总结一下,handler主要是用来handler可以分发和接收Message对象和Runnable对象,比如在UI主线程中创建一个Handler对象,可以把这个Handler理解为一个UI控件,Activity Looper不断刷新UI控件和handler,这样handler也就不会阻塞,利用这个不阻塞的handler从其它线程中获取数据。这样就像一个EditText从用户界面获取输入一样。这样理解handler是不是很形象。
一、Handler的定义:
Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用。比如可以用handler发送一个message,然后在handler的线程中来接收、处理该消息,以避免直接在UI主线程中处理事务导致影响UI主线程的其他处理工作,Android提供了Handler作为主线程和子线程的纽带;也可以将handler对象传给其他进程,以便在其他进程中通过handler给你发送事件;还可以通过handler的延时发送message,可以延时处理一些事务的处理。
通常情况下,当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发。如果此时需要一个耗时的操作,例如:联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收到Android系统的一个错误提示"强制关闭".
这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,但是当子线程中有涉及到操作UI的操作时,就会对主线程产生危险,也就是说,更新UI只能在主线程中更新,在子线程中操作是危险的. 这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对象,(里面包含数据), 把这些消息放入主线程队列中,配合主线程进行更新UI。
二、Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程), 也就是说Handler对象初始化后,就默认与对它初始化的进程的消息队列绑定,因此可以利用Handler所包含的消息队列,制定一些操作的顺序。
三、Handler中分发消息的一些方法
post类方法允许你排列一个Runnable对象到主线程队列中
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
四、应用实例:
1,传递Message。用于接受子线程发送的数据, 并用此数据配合主线程更新UI。
在Android中,对于UI的操作通常需要放在主线程中进行操作。如果在子线程中有关于UI的操作,那么就需要把数据消息作为一个Message对象发送到消息队列中,然后,用Handler中的handlerMessge方法处理传过来的数据信息,并操作UI。类sendMessage(Message msg)方法实现发送消息的操作。 在初始化Handler对象时重写的handleMessage方法来接收Messgae并进行相关操作。
2,传递Runnable对象。用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
Handler对象在进行初始化的时候,会默认的自动绑定消息队列。利用类post方法,可以将Runnable对象发送到消息队列中,按照队列的机制按顺序执行不同的Runnable对象中的run方法。
另外,Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。
对于Message,就不介绍了,平常用的最多。
这篇博文主要讲解使用Handle分发Runnable对象
下面给出一个小demo来介绍:
-
public class MainActivity extends ActionBarActivity{
-
private Button button;
-
private Button button2;
-
private Button button3;
-
/**
-
* 注意创建一个Handler对象,如果不带参数,调用Handler不带参数的构造函数,并将该handler对象绑定到创建它的线程的Looper,当然也可以传入参数指定关联的线
-
* 的Looper,UI主线程有Looper,如果指定的线程没有Looper,Handler不会接收message或者runnable,并且抛出异常。
-
*/
-
public Handler mHandler=new Handler();
-
-
Runnable runnable=new Runnable() {
-
@Override
-
public void run() {
-
System.out.println("--->>runnable work in thread:"+Thread.currentThread().getName());
-
}
-
};
-
-
@Override
-
public void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
button=(Button)this.findViewById(R.id.button);
-
button2=(Button)this.findViewById(R.id.button2);
-
button3=(Button)this.findViewById(R.id.button3);
-
-
/**
-
*要说明的是,由于runnable是一个接口,所以runnable还是在UI主线程中运行,我们从输出log中可以看出
-
*/
-
-
/**
-
* 发送runnable给Handler,runnable立即运行
-
*/
-
button.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
mHandler.post(runnable);
-
}
-
});
-
-
/**
-
* 发送runnable给Handler,runnable3秒后立即运行
-
*/
-
button2.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
mHandler.postDelayed(runnable,3000);
-
}
-
});
-
-
/**
-
* 通知Handler立即取消runnable
-
*/
-
button3.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
mHandler.removeCallbacks(runnable);
-
}
-
});
-
}
-
}
运行结果:
明显的可以看出runnable是在UI主线程中运行的,所以如果使用一个耗时操作,需要将Handler关联新线程。
对于Handler的其它方法,这里就不介绍了,参看:/docs/reference/android/os/Handler.html
推荐一篇好的文章:http://blog.sina.com.cn/s/blog_77c6324101016jp8.html
阅读(2123) | 评论(0) | 转发(0) |