android 实现主线程、子线程双向通信

在 android 中,不可以在子线程中更新 UI 的操作,否则会报错或者异常信息。

在这种情况下,我们会使用 Handler(在 UI 线程创建该对象) 接收子线程的消息更新 UI.

可以看出,这是子线程通知主线程,而主线程没有直接通知子线程,那麽我们如何做到这一点?这样有什么好处?

好处,很明显。主线程中如果有些耗时的操作,我们可以让子线程去做,这时,主线程就可以通知子线程了!


实现这种操作的方式有很多,今天主要想说说 HandlerThread 与 Handler 的配合使用方法。


在主线程中,可以创建 HandlerThread 对象:

  1. HandlerThread mHandlerThread = new HandlerThread("sub_thread");  
  2. mHandlerThread.start();  

这样,就开启了一个子线程,该线程的名字就是 sub_thread.


然后,我们实现一个继承自 Handler 的 MyHandler 类:

  1. class MyHandler extends Handler {  
  2.   
  3.         public MyHandler() {  
  4.             super();  
  5.         }  
  6.   
  7.         public MyHandler(Looper looper) {  
  8.             super(looper);  
  9.         }  
  10.           
  11.         @Override  
  12.         public void handleMessage(Message msg) {  
  13.             // super.handleMessage(msg);  
  14.             if(msg.what == MSG_WHAT) {  
  15.                 Bundle bundle = msg.getData();  
  16.                 String info = bundle.getString("main");  
  17.                 Log.d("mark""我接受任务:" + info);  
  18.             }  
  19.         }  
  20.     }  

最后,使用 Message 来传递消息,MyHandler 会根据情况处理 Message.


完整代码:

  1. package mark.zhang;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.HandlerThread;  
  7. import android.os.Looper;  
  8. import android.os.Message;  
  9. import android.util.Log;  
  10.   
  11. public class HandlerThreadActivity extends Activity {  
  12.   
  13.     private static final int MSG_WHAT = 1;  
  14.   
  15.     @Override  
  16.     public void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.main);  
  19.           
  20.         // 创建对象,并启动该线程  
  21.         HandlerThread mHandlerThread = new HandlerThread("sub_thread");  
  22.         mHandlerThread.start();  
  23.         // 获取 Looper 对象  
  24.         MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());  
  25.         // 创建 Bundle 对象,传递数据  
  26.         Bundle bundle = new Bundle();  
  27.         bundle.putString("main""我这边事情太多,麻烦你帮忙处理一下!");  
  28.         // 发送消息  
  29.         Message msg = new Message();  
  30.         msg.what = MSG_WHAT;  
  31.         msg.setData(bundle);  
  32.         msg.setTarget(mHandler);  
  33.         msg.sendToTarget();  
  34.           
  35.         Log.d("mark""UI----" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());  
  36.     }  
  37.   
  38.     /** 
  39.      * 该Handler调用 handleMessage方法运行在子线程 
  40.      *  
  41.      * @author mark 
  42.      */  
  43.     class MyHandler extends Handler {  
  44.   
  45.         public MyHandler() {  
  46.             super();  
  47.         }  
  48.           
  49.         /* 这个构造方法必须有 */  
  50.         public MyHandler(Looper looper) {  
  51.             super(looper);  
  52.         }  
  53.   
  54.         @Override  
  55.         public void handleMessage(Message msg) {  
  56.             if (msg.what == MSG_WHAT) {  
  57.                 Bundle bundle = msg.getData();  
  58.                 // 接收消息  
  59.                 String info = bundle.getString("main");  
  60.                 Log.d("mark""handleMessage---" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());  
  61.                 Log.d("mark""我接受任务:" + info);  
  62.             }  
  63.         }  
  64.     }  
  65. }  

这里,我们思考一个问题,代码:

  1. // 获取 Looper 对象  
  2. MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());  

获取 Looper 对象,使用的是 HandlerThread 对象的 getLooper 对象。为什么不直接这样:

  1. // 获取 Looper 对象  
  2. MyHandler mHandler = new MyHandler(getMainLooper());  

如果这样做的话,打印信息如下:

  1. D/mark    (21852): UI----threadName: main,threadId: 1  
  2. D/mark    (21852): handleMessage---threadName: main,threadId: 1  
  3. D/mark    (21852): 我接受任务:我这边事情太多,麻烦你帮忙处理一下!  

可见,此时的 handleMessage 是在主线程中运行的。每个主线程默认有一个 Looper,也就是说在主线程中,下面代码是等效的:

  1. MyHandler mHandler = new MyHandler(getMainLooper());  
  2.   
  3. MyHandler mHandler = new MyHandler();  

但是子线程需要手动获取如:

  1. MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());  

实现主线程、子线程双向通信可以在各自的线程中分别是用 Handler 来传递信息和处理消息。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值