您的位置:首页 > 运维架构

handler与looper的关系及HandlerThread

2015-07-12 23:36 471 查看
做了也快2年的android了,发现android的机制还不是很了解,这几天看了一下这方面的介绍,总结一下handler的用法和机制。handler就是用来线程之间通信的,主线程与子线程。一般的用法是,子线程通知ui主线程的handler去刷新ui操作。最近遇到一些人,问能不能主线程去通知子线程的handler。当然是可以的。贴一个例子
package cc.c;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;
/**
* Demo描述:
*
* 示例步骤如下:
* 1 子线程给子线程本身发送消息
* 2 收到1的消息后,子线程给主线程发送消息
* 3 收到2的消息后,主线程给子线程发送消息
*
* 为实现子线程给自己本身发送消息,关键还是在于构造Handler时传入的Looper.
* 在此就传入该子线程自己的Looper即调用Looper.myLooper(),代码如下:
* Looper.prepare();
* mHandlerTest1=new HandlerTest1(Looper.myLooper());
* Looper.loop();
*
* 所以当mHandlerTest1.sendMessage(message);发送消息时
* 当然是发送到了它自己的消息队列.
*
* 当子线程中收到自己发送的消息后,可继续发送消息到主线程.此时只要注意构造
* Handler时传入的Handler是主线程的Handler即可,即getMainLooper().
* 其余没啥可说的.
*
*
* 在主线程处理消息后再发消息到子线程
*
*
* 其实这些线程间发送消息,没有什么;关键还是在于构造Handler时传入谁的Looper.
*
*/
public class MainActivity extends Activity {
private TextView mTextView;
private HandlerTest1 mHandlerTest1;
private HandlerTest2 mHandlerTest2;
private int counter=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}

private void init() {
mTextView = (TextView) findViewById(R.id.textView);

//1 子线程发送消息给本身
new Thread() {
public void run() {
Looper.prepare();
mHandlerTest1=new HandlerTest1(Looper.myLooper());
Message message = new Message();
message.obj = "子线程发送的消息Hi~Hi";
mHandlerTest1.sendMessage(message);
Looper.loop();
};
}.start();

}

private class HandlerTest1 extends Handler {

private HandlerTest1(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
System.out.println("子线程收到:" + msg.obj);

//2  收到消息后可再发消息到主线程
mHandlerTest2=new HandlerTest2(getMainLooper());
Message message = new Message();
message.obj = "O(∩_∩)O";
mHandlerTest2.sendMessage(message);
}
}

private class HandlerTest2 extends Handler {

private HandlerTest2(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText("在主线程中,收到子线程发来消息:" + msg.obj);

//3  收到消息后再发消息到子线程
if (counter==0) {
Message message = new Message();
message.obj = "主线程发送的消息Xi~Xi";
mHandlerTest1.sendMessage(message);
counter++;
}

}
}

}
这个就很好的展示了,子线程主线程都是可以有handler,可以互相传递消息的。必须要明确的是handler必须要绑定一个looper。
但是区别在于,子线程需要做

Looper.prepare();

Looper.loop();
这两个方法,而主线程不需要。因为主线程在启动的时候会初始化looper,如下:

 Android程序的运行入口点可以认为是android.app.ActivityThread类的main()方法(源码2.3.3):
public static final void main(String[] args) {
// other codes...

// 创建主线程循环
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}

ActivityThread thread = new ActivityThread();
thread.attach(false);

// other codes...

// 进入当前线程(此时是主线程)消息循环
Looper.loop();

// other codes...

thread.detach();
// other codes...
}
所以可以看到,如果要有消息循环的话,线程中任何时候都必须要有初始化looper的过程,只不过主线程在启动的时候已经帮我们完成,而子线程需要自己去实现。(需要注意的是,如果我们在ui线程中new handler而不做绑定,那么默认的认为handler是绑定主线程的looper,所以我们就可以想到,ui线程中new handler也可以绑定子线程的looper,即handlerThread的用法)另外一个是,handlerThread,参考下面的解释:在上面的总结中指出,Android的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程一般都会有一个Looper。事实上Android提供了一个封装好的带有looper的线程类,即为HandlerThread,具体可参见下面的代码:
public class HandlerThreadActivity extends Activity {

private static final String TAG = "HandlerThreadActivity";

private HandlerThreadmHandlerThread;

private MyHandler mMyHandler;

@Override

protected void onCreate(Bundle savedInstanceState) {

// TODO Auto-generatedmethod stub

super.onCreate(savedInstanceState);

TextView text = new TextView(this);

text.setText("HandlerThreadActivity");

setContentView(text);

Log.d(TAG, "The mainthread id = " +      Thread.currentThread().getId());

//生成一个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) {

Log.d(TAG, "MyHandler-->handleMessage-->threadid = " + Thread.currentThread().getId());

super.handleMessage(msg);

}

}

}
可以看到在该段代码中,在子线程中有 mHandlerThread = new HandlerThread("handler_thread"),然后在主线程中的hanler是绑定该线程的loooper的,mMyHandler = new MyHandler(mHandlerThread.getLooper());我的理解的话,HandlerThread与thread的区别不大,因为HandlerThread是继承自thread的,只不过HandlerThread提供了默认的Looper。总结一下:1、handler是android提供的一种消息循环机制,为多线程提供了很大的帮助,特别是异步获取数据然后刷新ui的操作。2、handler与looper是共生的,一个线程只有一个looper,只不过有的线程已经做好了初始化looper的操作(ui线程,HandlerThread),而其他子线程需要自己做。3、handler通过绑定特定线程的looper,可以实现在该线程中向某一个looper发送消息,就可以在这个handler中处理了。如子线程中通过
Looper.prepare();mHandlerTest1=new HandlerTest1(Looper.myLooper());
绑定自己的looper,
也可以mHandlerTest2=new HandlerTest2(getMainLooper());绑定ui的looper都是可以的,
然后主线程中也棒子子线程的looper,就看你如何绑定哪个looper了。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: