标签:
android中Handle类的主要作用:
1.在新启动的线程中发送消息
2.在主线程获取、处理消息
为什么要用Handle这样的一个机制:
因为在Android系统中UI操作并不是线程安全的,如果多个线程并发的去操作同一个组件,可能导致线程安全问题。为了解决这一个问题,android制定了一条规则:只允许UI线程来修改UI组件的属性等,也就是说必须单线程模型,这样导致如果在UI界面进行一个耗时叫长的数据更新等就会形成程序假死现象 也就是ANR异常,如果20秒中没有完成程序就会强制关闭。所以比如另一个线程要修改UI组件的时候,就需要借助Handler消息机制了。
Handle发送和处理消息的几个方法:
1. void handleMessage( Message msg):处理消息的方法,该方法通常被重写。
2.final boolean hasMessage(int what):检查消息队列中是否包含有what属性为指定值的消息
3.final boolean hasMessage(int what ,Object object) :检查消息队列中是否包含有what好object属性指定值的消息
4.sendEmptyMessage(int what):发送空消息
5.final Boolean send EmptyMessageDelayed(int what ,long delayMillis):指定多少毫秒发送空消息
6.final boolean sendMessage(Message msg):立即发送消息
7.final boolean sendMessageDelayed(Message msg,long delayMillis):多少秒之后发送消息
与Handle工作的几个组件Looper、MessageQueue各自的作用:
1.Handler:它把消息发送给Looper管理的MessageQueue,并负责处理Looper分给它的消息
2.MessageQueue:采用先进的方式来管理Message
3.Looper:每个线程只有一个Looper,比如UI线程中,系统会默认的初始化一个Looper对象,它负责管理MessageQueue,不断的从MessageQueue中取消息,并将相对应的消息分给Handler处理
在线程中使用Handler的步骤:
1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会自动的创建相对应的MessageQueue
2.创建Handler子类的实例,重写HandleMessage()方法,该方法处理除UI线程以外线程的消息
3.调用Looper的loop()方法来启动Looper
1. 申请一个Handler对象
Handler handler = new Handler();
2. 创建一个线程
{继承Thread类或者实现Runnable这个接口}
使用Runnable创建一个内部匿名类对象updateThread(要复写run方法)
3. 使用handler的post方法将线程加入到线程队列中
handler.post(updateThread);
4. 使用handler的removeCallbacks方法移出updateThread线程
注意:如果线程从线程队列中出来被执行后,则队列中就不在有线程
因此如果线程在被执行后没有方法将其再次加入到队列中,则无需使用removeCallbacks
线程走出线程队列有两种情况:
一种是被执行,此时要执行run方法
一种是使用removeCallbacks方法,此时线程不被执行,因此不调用run
5. 使用handler的postDelayed方法延时将线程加入到队列中
handler.postDelayed(updateThread,3000)
注意:用post方法将线程对象放到队列里面执行,并没有开启一个新的线程,而是直接调用线程
对象的run方法,因此并没有实现线程的异步。
解决的办法是先生成一个HandlerThread对象,启动它(start)
使用handlerThread对象的getLooper方法取得其looper对象,注意在此之前必须要start,否则这个looper是空的
并将looper对象作为参数传递给handler对象,使得这个handler对象绑定到这个Looper所在线程上面
此时需要重写handler类的构造函数,将looper对象传给父类
Looper:类,提供一种循环的从队列当中取得消息的功能,不要自己创建
这样,这个handler就可以循环的从Message消息队列中不断取消息。
Handler的作用
1.1发送和处理消息
首先在Activity中创建一个继承自Handler的匿名内部类以及这个类的一个对象
private class MainHandler extends Handler {
public voidhandleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_MAIN_HANDLER_TEST:
Log.d(TAG, "MainHandler-->handleMessage-->thread id =" + Thread.currentThread().getId());
break;
}
}
};
这样在Activity的其他地方就可以通过mMainHandler对象发送消息给Handler处理了
Message msg = mMainHandler.obtainMessage(MSG_MAIN_HANDLER_TEST);
mMainHandler.sendMessage(msg);
1.2处理runnables方法中的代码
除了上述的使用Handler发送以及处理消息外,handler还有一个作用就是处理传递给它的action对象,具体使用步骤示例:
1、在主线程中定义Handler对象
2、构造一个runnable对象,为该对象实现runnable方法。
3、在子线程中使用Handler对象post(runnable)对象.
handler.post这个函数的作用是把Runnable里面的run方法里面的这段代码发送到消息队列中,等待运行。
如果handler是以UI线程消息队列为参数构造的,那么是把run里面的代码发送到UI线程中,等待UI线程运行这段代码。
如果handler是以子线程线程消息队列为参数构造的,那么是把run里面的代码发送到子线程中,等待子线程运行这段代码。
Runnable 并不一定是新开一个线程,比如下面的代码中就是运行在UI主线程中的:
public class TestActivity extends Activity implementsOnClickListener {
/** Calledwhen the activity is first created. */
private Button mBtnTest=null;
private Handler myHandler=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBtnTest=(Button)findViewById(R.id.btn_test);
mBtnTest.setOnClickListener(this);
myHandler=new Handler();
}
@Override
public void onClick(View v) {
//注意:此处UI线程被阻塞,因为myHandler是在UI线程中创建的
myHandler.post(new Runnable() {
public void run() {
long i=0;
while(true){
i++;
}}});}}
handler的消息发送与Post方法有什么区别呢?
Handler对象消息发送sendXXXX相关方法如下,同时还有postXXXX相关方法, 这些和Win32中的道理基本一致,一个为发送后直接返回,一个为处理后才返回。
1.3线程间通信
下面代码中红色标注处即为在MyThread这个线程中,通过UI线程中的handler向UI线程发送消息。
class MyThread extends Thread{
Handler mHandler;
Boolean boo;
publicMyThread(Handler handler){
mHandler = handler;
}
publicvoid setBoo(boolean b) {boo = b; }
publid void run(){
if(boo){
getWeatherInfo();//耗时操作
analyzing();//耗时操作
mHandler.post(newRunnable() {
publicvoid run() {
setWeather();//更新UI
});//更新UI
boo = true;
}
}
}
在处理单击事件时:
sureButton.setOnClickListener(newButton.OnClickListener(){
public void onClick(View view){
setBoo(true);
myThread.start();
}
});
在activity中:
MyThread myThread = new MyThread(mHandler);
其中mHandler为在UI线程中创建的。
2职责与关系
Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Messagemsg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个 Looper的同时,会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
这样说来,多个Handler都可以共享同一Looper和MessageQueue了。当然,这些Handler也就运行在同一个线程里。
Android的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。事实上Android提供了一个封装好的带有looper的线程类,即为HandlerThread。
3.不是所有的Handler都能更新UI
Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中,不乏更新UI的操作,不正确的线程直接更新UI将引发异常。因此,需要时刻关心Handler在哪个线程里创建的。如何更新UI才能不出异常呢?SDK告诉我们,有以下4种方式可以从其它线程访问UI线程(也即线程间通信):
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
在UI线程中创建的Handler
其中,重点说一下的是View.post(Runnable)方法。在post(Runnableaction)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在 Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。
几点小结
Handler的处理过程运行在创建Handler的线程里
一个Looper对应一个MessageQueue,一个线程对应一个Looper,一个Looper可以对应多个Handler
不确定当前线程时,更新UI时尽量调用View.post方法
handler应该由处理消息的线程创建。
handler与创建它的线程相关联,而且也只与创建它的线程相关联。handler运行在创建它的线程中,所以,如果在handler中进行耗时的操作,会阻塞创建它的线程。
Android的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。主线程(UI线程)就是一个消息循环的线程。
Looper.myLooper(); //获得当前的Looper
Looper.getMainLooper() //获得UI线程的Lopper
Handle的初始化函数(构造函数),如果没有参数,那么他就默认使用的是当前的Looper,如果有Looper参数,就是用对应的线程的Looper。
如果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用Looper.loop();之后就进入了消息循环,这个之后就可以发消息、取消息、和处理消息。
在上面的总结中指出,Android的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。事实上Android提供了一个封装好的带有looper的线程类,即为HandlerThread,具体可参见下面的代码
public class HandlerThreadActivity extends Activity {
private static final String TAG = "HandlerThreadActivity";
private HandlerThread mHandlerThread;
private MyHandler mMyHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView text = new TextView(this);
text.setText("HandlerThreadActivity");
setContentView(text);
//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,
//这个类由Android应用程序框架提供
mHandlerThread = new HandlerThread("handler_thread");
//在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();
mHandlerThread.start();
//即这个Handler是运行在mHandlerThread这个线程中
mMyHandler = new MyHandler(mHandlerThread.getLooper());
mMyHandler.sendEmptyMessage(1);
}
private class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
}
标签:
原文地址:http://www.cnblogs.com/lin-lin/p/4306590.html