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++; } } } }
main.xml以下:android
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" android:layout_centerInParent="true" android:layout_marginTop="70dip" /> </RelativeLayout>
1.线程没有终止条件,会一直给主线程发消息,主线程不停的调用handleMessage代码,很容易ANR(应用程序不响应)
2.handler.obtainMessage()获得message对象比new Message();更高效
多线程
Handler对象与其调用者在同一线程中,若是在Handler中设置了延时操做,则调用线程也会堵塞。每一个Handler对象都会绑定一个Looper对象,每一个Looper对象对应一个消息队列(MessageQueue)。若是在建立Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
在主线程中,能够直接使用new Handler()建立Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样建立Handler则会报错,由于Android系统默认状况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。这种状况下,需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),而后将其绑定到Handler对象上;或者经过Looper.getMainLooper(),得到主线程的Looper,将其绑定到此Handler对象上。
Handler发送的消息都会加入到Looper的MessageQueue中。一说Handler包含两个队列:线程队列和消息队列;使用Handler.post()能够将线程对象加入到线程队列中;使用Handler.sendMessage()能够将消息对象加入到消息队列中。经过源码分析证明,Handler只有一个消息队列,即MessageQueue。经过post()传进去的线程对象将会被封装成消息对象后传入MessageQueue。
使用post()将线程对象放到消息队列中后,当Looper轮询到该线程执行时,实际上并不会单独开启一个新线程,而仍然在当前Looper绑定的线程中执行,Handler只是调用了该线程对象的run()而已。如,在子线程中定义了更新UI的指令,若直接开启将该线程执行,则会报错;而经过post()将其加入到主线程的Looper中并执行,就能够实现UI的更新。
使用sendMessage()将消息对象加入到消息队列后,当Looper轮询到该消息时,就会调用Handler的handleMessage()来对其进行处理。再以更新UI为例,使用这种方法的话,就先将主线程的Looper绑定在Handler对象上,重载handleMessage()来处理UI更新,而后向其发送消息就能够了。app