Android Handler实现子线程与子线程、主线程之间通信

一、子线程向主线程传值:

首选在主线程里创建一个Handler

 1 Handler mHandler = new Handler(){    
 2     @Override  
 3     public void handleMessage(Message msg) {  
 4         super.handleMessage(msg);  
 5         switch (msg.what) {  
 6         case 0:  
 7             //do something,refresh UI;  
 8             break;  
 9         default:  
10             break;  
11         }  
12     }  
13 };  
  • 然后开启一个子线程,在子线程里直接使用Handler发送消息即可
1 new Thread() {
2             public void run() {
3                 Message message = new Message();
4                 message.obj = "子线程发送的消息Hi~Hi";
5                 mHandler .sendMessage(message);
6             };
7         }.start();
  • 二、主线程向子线程里发送消息:

主线程向子线程发送消息的话,我们需要在子线程里初始化Looper,并在主线程里创建的Handler引用子线程的Looper(Handler中引用的是哪个线程的Looper,就在哪个线程里处理消息)

 1  public class ThreadHandlerActivity extends Activity{     
 2      //创建子线程
 3      class MyThread extends Thread{
 4          private Looper looper;//取出该子线程的Looper
 5          public void run() {
 6  
 7              Looper.prepare();//创建该子线程的Looper
 8              looper = Looper.myLooper();//取出该子线程的Looper
 9              Looper.loop();//只要调用了该方法才能不断循环取出消息
10          }
11      }
12  
13      private Handler mHandler;//将mHandler指定轮询的Looper
14  
15      protected void onCreate(Bundle savedInstanceState) {
16              super.onCreate(savedInstanceState);
17              setContentView(R.layout.main);
18              thread = new MyThread();
19              thread.start();//千万别忘记开启这个线程
20              //下面是主线程发送消息
21           mHandler = new Handler(thread.looper){
22               public void handleMessage(android.os.Message msg) {
23            Log.d("当前子线程是----->",Thread.currentThread()+"");
24                  };
25              };
26              mHandler.sendEmptyMessage(1);
27      }
28  
29  }

其实这样就可以达到主线程向子线程发送消息了,然而当我们运行后发现程序会Crash掉,报了一个空指针,这是因为在Handler初始化的时候,thread.looper还没有初始化,所以会报空指针,这时我们可以让主线程等待一下子线程,也可以来一个while循环来判断thread.looper是否初始化完成。不过Android本身还提供了一个方法,那就是HandlerThread:

 1      protected void onCreate(Bundle savedInstanceState) {
 2              super.onCreate(savedInstanceState);
 3              tv = new TextView(this);
 4              tv.setText("Handler实验");
 5              setContentView(tv);
 6  
 7              //实例化一个特殊的线程HandlerThread,必须给其指定一个名字
 8             HandlerThread thread = new HandlerThread("handler thread");
 9              thread.start();//千万不要忘记开启这个线程
10              //将mHandler与thread相关联
11              mHandler = new Handler(thread.getLooper()){
12                  public void handleMessage(android.os.Message msg) {
13                      Log.d("当前子线程是----->", Thread.currentThread()+"");
14                  };
15              };
16              mHandler.sendEmptyMessage(1);//发送消息
17      }

这时HandlerMessage所在的线程就是HandlerThread 的子线程。
然而HandlerThread 所创建处理的子线程里是不能重写Run()方法的,你写了以后,会发现,HandlerMessage不执行了,这时因为HandlerMessage本身实现了Run()方法,我们看一下内部实现:

 1 @Override
 2      public void run() {
 3          mTid = Process.myTid();
 4          Looper.prepare();
 5          synchronized (this) {
 6              mLooper = Looper.myLooper();
 7              notifyAll();
 8          }
 9          Process.setThreadPriority(mPriority);
10          onLooperPrepared();
11          Looper.loop();
12          mTid = -1;
13      }

在源代码的第4行,进行了实例化自己的Looper,如果继续追踪源代码翻看其getLooper方法你会发现,如果一个Handler在与HandlerThread进行绑定时,发现Looper为空,Handler则会一直等待直到Looper被创建出来为止,然后才继续执行后续的代码。所以我们重写了HandlerThread的run方法,肯定就不会去创建Looper对象,那么绑定的Handler就会永远处于等待状态,自然而然就不会执行到HandlerMessage信息了。这也是为什么我们要使用HandlerThread这个特殊的线程,因为使用这个,我们不必关心多线程会混乱,Looper会为空等一系列问题,只要去关心我们要实现的逻辑就行了。

三、子线程和子线程之间通信:

其实子线程向子线程之间通信,其实就是在一个子线程中创建一个Handler,它的回调自然就在此子线程中,然后在另一个子线程中调用此handler来发送消息就可以了,不过记得写上Looper哦,下面看代码:

 1 new Thread(new Runnable() {
 2  
 3                       @Override
 4                       public void run() {
 5                           String msg;
 6                           Looper.prepare();
 7  
 8                           childHandler = new Handler() {
 9                               @Override
10                     public void handleMessage(Message msg) {
11                                  super.handleMessage(msg);
12  
13                                  System.out.println("这个消息是从-->>" + msg.obj+ "过来的,在" + "btn的子线程当中" + "中执行的");
14  
15                              }
16  
17                          };  
18                       Looper.loop();//开始轮循
19  
20                      }
21                  }).start();
  • 其中 Looper.prepare()和Looper.loop()一定不要忘了写。

然后我们创建第二个子线程

 1 new Thread(new Runnable() {
 2  
 3                       @Override
 4                       public void run() {
 5                          Looper loop = Looper.myLooper();
 6                Message msg = childHandler.obtainMessage();
 7                          msg.obj = "btn2当中子线程";
 8                          childHandler.sendMessage(msg);
 9                      }
10                  }).start();

 

posted on 2022-07-12 17:32  Bytezero!  阅读(3058)  评论(0编辑  收藏  举报