`
云端的Android
  • 浏览: 61651 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

Handler: 主线程如何通知子线程(转)

 
阅读更多

      在 android 中,不可以在子线程中更新 UI 的操作,否则会报错或者异常信息。 在这种情况下,我们会使用 Handler(在 UI 线程创建该对象) 接收子线程的消息更新 UI. 可以看出,这是子线程通知主线程,而主线程没有直接通知子线程,那麽我们如何做到这一点?这样有什么好处? 好处,很明显。主线程中如果有些耗时的操作,我们可以让子线程去做,这时,主线程就可以通知子线程了!

        实现这种操作的方式有很多,今天主要想说说 HandlerThread 与 Handler 的配合使用方法。在主线程中,可以创建 HandlerThread 对象:

 

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

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

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

 

class MyHandler extends Handler {  
  
        public MyHandler() {  
            super();  
        }  
  
        public MyHandler(Looper looper) {  
            super(looper);  
        }  
          
        @Override  
        public void handleMessage(Message msg) {  
            // super.handleMessage(msg);  
            if(msg.what == MSG_WHAT) {  
                Bundle bundle = msg.getData();  
                String info = bundle.getString("main");  
                Log.d("mark", "我接受任务:" + info);  
            }  
        }  
    }  

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

完整代码:

 

package mark.zhang;  
  
import android.app.Activity;  
import android.os.Bundle;  
import android.os.Handler;  
import android.os.HandlerThread;  
import android.os.Looper;  
import android.os.Message;  
import android.util.Log;  
  
public class HandlerThreadActivity extends Activity {  
  
    private static final int MSG_WHAT = 1;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        // 创建对象,并启动该线程  
        HandlerThread mHandlerThread = new HandlerThread("sub_thread");  
        mHandlerThread.start();  
        // 获取 Looper 对象  
        MyHandler mHandler = new MyHandler(mHandlerThread.getLooper());  
        // 创建 Bundle 对象,传递数据  
        Bundle bundle = new Bundle();  
        bundle.putString("main", "我这边事情太多,麻烦你帮忙处理一下!");  
        // 发送消息  
        Message msg = new Message();  
        msg.what = MSG_WHAT;  
        msg.setData(bundle);  
        msg.setTarget(mHandler);  
        msg.sendToTarget();  
          
        Log.d("mark", "UI----" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());  
    }  
  
    /** 
     * 该Handler调用 handleMessage方法运行在子线程 
     *  
     * @author mark 
     */  
    class MyHandler extends Handler {  
  
        public MyHandler() {  
            super();  
        }  
          
        /* 这个构造方法必须有 */  
        public MyHandler(Looper looper) {  
            super(looper);  
        }  
  
        @Override  
        public void handleMessage(Message msg) {  
            if (msg.what == MSG_WHAT) {  
                Bundle bundle = msg.getData();  
                // 接收消息  
                String info = bundle.getString("main");  
                Log.d("mark", "handleMessage---" + "threadName: " + Thread.currentThread().getName() + ",threadId: " + Thread.currentThread().getId());  
                Log.d("mark", "我接受任务:" + info);  
            }  
        }  
    }  
}  

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

 

  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 来传递信息和处理消息。

分享到:
评论

相关推荐

    Handler主线程于子线程,子线程与子线程,主线程到子线程消息传递

    Handler消息传递详解,子线程到子线程,主线程到子线程,子线程到主线程 三种消息,Looper,Handler工作机制详解 https://blog.csdn.net/shoneworn/article/details/80447651

    Android Handler主线程和一般线程通信的应用分析

    Handler的定义:主要接受子线程发送的数据, 并用此数据配合主线程更新UI.解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个...

    利用Handler在线程之间传递数据

    这个demo介绍了通过Handler在线程之间传递消息,demo中一个三个线程,主线程,发送消息的分线程,接收消息的分线程。发送消息的分线程会通知主线程更改标签文字,同时会通知接收消息的分线程更改进度条的进度。

    android主线程、子线程及线程间通信方式测试app

    测试Android主线程、子线程(thread、handlerThread、AsyncTask、timer)及线程间通信方式(handler、timetask、Runnable)的建立及工作过程

    android 主线程给子线程发送消息

    这是我自己写的demo,练习在android中主线程给子线程发送消息

    【面试】可以在子线程直接new一个Handler吗?怎么做?

    可以在子线程直接new一个Handler,不过需要在子线程里先调用Looper.prepare(),new一个Handler后,还需要调用Looper.loop()方法。 new Thread(new Runnable() { @Override public void run() { Looper.prepare()...

    android主线程和子线程之间消息传递详解

    从主线程发送消息到子线程(准确地说应该是非UI线程) package com.zhuozhuo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os....

    线程与handler

    实现的应用为一加法器,在thread中时行计算,主线程通过handler传递参数给thread,theread处理完后再通过handler传回主线程。如果只是实现加法器,没有必要整个线程和handler,主要的目的在于数据在不同线程通过...

    Android-TestCallBack:接口回调 主线程调用子线程的方法 HttpClient Handler

    Android-TestCallBack接口回调 主线程调用子线程的方法 HttpClient Handler出错:开始时,在AndroidManifest.xml中,启动的activity写错.然后,出现,网址的字符出错,参数不合法.还没有解决.

    Android中利用Handler在子线程中更新界面--简单的小球上下跳动案例

    处理不好会导致系统假死,用户体验很差,而Android则更进一步,如果任意一个Acitivity没有响应5秒钟以上就会被强制关闭,因此我们需要另外起动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送...

    安卓handler的使用

    handler的使用演示,主线程给子线程发消息,子线程给主线程发消息

    Android主线程给多个线程发送消息

    经过探索,我发现可以实现一个主线程给多个线程发送消息,主线程接收每个线程的内容进行处理 下面是我改造的例子:

    Android 多线程:使用Thread和Handler

    当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关...所以主线程通常又被叫做UI线程。

    子线程和主线程5种交互方式 Demo

    android 中的五中子线程和主线程交互方式,可针对整个activity的UI或者单个View

    Android 线程开发 开发实例

    例如一个子线程从网络上下载了一副图片,当它下载完成后会发送消息给主线程,这个消息是通过绑定在主线程的Handler来传递的。 在Android,这里的线程分为有消息循环的线程和没有消息循环的线程,有消息循环的线程...

    Android Handler Looper Message 使用示例

    在主线程即UI线程外,新建一个Looper线程,并用Messenger和Handler来处理message和posted runnable。程序中,在负线程中默认加了一个3s的线程等来,来帮助理解sent message和post runnable之间的同步机制。所以在按...

    异步线程AsyncTask

    首先明确Android之所以有Handler和AsyncTask 都是为了不阻塞主线程(UI线程) 且UI的更新只能在主线程中完成 因此异步处理是不可避免的 Android为了降低这个开发难度 提供了AsyncTask AsyncTask就是一个封装过的...

    android开发教程之子线程中更新界面

    在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息。当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于...

    android线程消息机制之Handler详解

    平常在开发中,我们常用来在子线程中通知主线程来更新,其实整个安卓生命周期的驱动都是通过Handler(ActivityThread.H)来实现的。 首先我们先介绍这四个类的作用: Handler:消息的发送者。负责将Message消息发送到...

Global site tag (gtag.js) - Google Analytics