在我们使用Handler传递信息时,其实都是通过Looper通道的,当建立一个Handler对象时都是通过了LOOPER平时我们都是自动生成,但是当使用到用户自定义类handler就要自己手工调。
下面实现一个实例讲述looper作用:
布局文件代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/but"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="22dp"
android:onClick="click"
android:text="启动" />
</LinearLayout>
主Activity代码:
public class MainActivity extends Activity {
private TextView info;
private static final int set=1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.info=(TextView)super.findViewById(R.id.info);
}
public void click(View v){
switch(v.getId()){
case R.id.but:
Looper looper=Looper.myLooper();
MyHandler myhandler=new MyHandler(looper);
myhandler.removeMessages(0);//清空所有的消息队列
String data="ee工作室创造科技前沿";
Message msg=myhandler.obtainMessage(set, 1, 1,data);
myhandler.sendMessage(msg);
break;
}
}
private class MyHandler extends Handler{
public MyHandler(Looper looper){
super(looper);
}
public void handleMessage(Message msg){
switch(msg.what){
case 1:
MainActivity.this.info.setText(msg.obj.toString());
}
}
}
}
显示效果如下:
看到这里你是不是举得奇怪,就是明明不用Looper只用Handler和Message也能实现这样的功能。那么接下来我们要变形啦,用另一种变形代码深入理解Looper通道
在主线程子线程各自设置一个Handler处理,并且开启通道,通道会不惑目前使用通道的线程。通道因为是隐式我们只能通过这种方式了解主子线程传递消息的过程
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@+id/info"
android:text="等待子线程发送消息"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/but"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="22dp"
android:onClick="click"
android:text="交互" />
</LinearLayout>
这里info实现显示主线程接收到的信息,按键表示主线程发送给子线程的信息
主函数代码
ublic class MainActivity extends Activity {
private TextView info;
private static final int SetMain = 1;
private static final int SetChild = 2;
private Handler mainHandler, childHandler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.info = (TextView) super.findViewById(R.id.info);
MainActivity.this.mainHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SetMain:
MainActivity.this.info.setText("主线程接受到的数据: "+msg.obj.toString());
}
}
};
new Thread(new ChildThread(),"child thread").start();
}
public void click(View v) {
if(MainActivity.this.childHandler!=null){
Message childmsg=MainActivity.this.childHandler.obtainMessage();
childmsg.obj=MainActivity.this.mainHandler.getLooper().getThread().getName()
+"--->儿子我来啦";
childmsg.what=SetChild;
MainActivity.this.childHandler.sendMessage(childmsg);
}
}
protected void onDestroy(){
super.onDestroy();
MainActivity.this.childHandler.getLooper().quit();//结束队列
}
private class ChildThread implements Runnable {
public void run() {
Looper.prepare();//初始化队列
MainActivity.this.childHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case SetChild:
System.out.println("主线程发给子线程的消息: "+msg.obj);
//创建Message发给主线程
Message toMain=MainActivity.this.childHandler.obtainMessage();
toMain.obj="这是子线程发给主线程的消息:"+super.getLooper().getThread().getName();
toMain.what=SetMain;
MainActivity.this.mainHandler.sendMessage(toMain);
}
}
};
Looper.loop();//启动该线程的消息队列
}
}
}
这里很重要一点是建立Looper通道,如果不建立,子线程无法向主线程发送消息
首先我们按交互按钮,控制台输出:
这里说明子线程接受到了主线程发送的信息,并且显示当前使用通道线程是main主线程
主线程接收效果
同理学到这里相信还是很多人有疑问,当主线程发送给子线程的信息为什么不直接更新在UI上,反而要通过后天输出,这里还是强调一点,在安卓中,不支持子线程直接向UI更新,如果要实现的话,就只使用一个handler实现。