`
gjhappyyy
  • 浏览: 260588 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

Android Handler机制

 
阅读更多

最近看到一篇文章,关于Handler和Looper的。觉得写的很好。这里和大家分享一下。

 在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知

    handler基本使用:

        在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法,在handleMessage中
提供收到消息后相应的处理方法即可,这里不对handler使用进行详细说明,在看本博文前,读者应该先掌握handler的基本使用,我这里主要深入描述handler的内部机制

   .现在我们首先就有一个问题,我们使用myThreadHandler.sendEmptyMessage(0);发送一个message对象,那么Handler是如何接收该message对象并处理的呢?我先画一个数据结构图:

    

从这个图中我们很清楚可以看到调用sendEmptyMessage后,会把Message对象放入一个MessageQueue队列,该队列属于某个Looper对象,每个Looper对象通过ThreadLocal.set(new Looper())跟一个Thread绑定了,Looper对象所属的线程在Looper.Loop方法中循环执行从MessageQueue队列读取Message对象,并把Message对象交由Handler处理,调用Handler的dispatchMessage方法。

     现在我们再来看一下使用Handler的基本实现代码:

               // 主线程中新建一个handler
                normalHandler = new Handler() {
                        public void handleMessage(android.os.Message msg) {
                                btnSendMsg2NormalHandler.setText("normalHandler");
                                Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--normalHandler handleMessage run...", Thread.currentThread()
                                                .getName()));
                        }
                };

...
//发送消息到hanlder
myThreadHandler.sendEmptyMessage(0); 

你现在已经很清楚了sendEmptyMessage到handleMessage的过程,途中经过Looper.MessageQueue队列,转由Looper所在的线程去处理了,这是一个异步的过程,当然Looper所在的线程也可以是sendEmptyMessage所在的线程。 

     看了上面你也许还是迷惑不解,那么什么要Looper了,跟我们要用的Handler又有啥鸟关系呢?

     我在前面一直强调在主线程中使用handler,为什么要这么说呢,因为你在自己new一个新线程中去像我前面那样简单建立一个Handler,程序执行是会报错的:

    java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
     at android.os.Handler.<init>(Handler.java:121)
     at com.cao.android.demos.handles.HandleTestActivity$MyThread$1.<init>(HandleTestActivity.java:86)
     at com.cao.android.demos.handles.HandleTestActivity$MyThread.run(HandleTestActivity.java:86)

    为什么在主线程中不会报错,而在自己新见的线程中就会报这个错误呢?很简单,因为主线程它已经建立了Looper,你可以打开ActivityThread的源码看一下:

    public static final void main(String[] args) {
        SamplingProfilerIntegration.start();

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        Looper.loop();

        if (Process.supportsProcesses()) {
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        thread.detach();
        String name = (thread.mInitialApplication != null)
            ? thread.mInitialApplication.getPackageName()
            : "<unknown>";
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

    在main函数中它已经做了这个事情了,为什么要调用 Looper.prepareMainLooper(); Looper.loop();我们可以进去看一下,在prepareMainLooper方法中新建了一个looper对象,并与当前进程进行了绑定,而在Looper.loop方法中,线程建立消息循环机制,循环从MessageQueue获取Message对象,调用  msg.target.dispatchMessage(msg);进行处理msg.target在myThreadHandler.sendEmptyMessage(0)设置进去的,因为一个Thead中可以建立多个Hander,通过msg.target保证MessageQueue中的每个msg交由发送message的handler进行处理,那么Handler又是怎样与Looper建立联系的呢,在Handler构造函数中有这样一段代码:

       mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;

在新建Handler时需要设置mLooper成员,Looper.myLooper是从当前线程中获取绑定的Looper对象:

public static final Looper myLooper() {
        return 
(Looper)sThreadLocal.get();
    }

    若Looper对象没有创建,就会抛异常"Can't create handler inside thread that has not called Looper.prepare()"
这跟我前面讲的是一致的。所以我们在一个新线程中要创建一个Handler就需要这样写:

        class MyThread extends Thread {

                public void run() {                
                        Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]-- run...", Thread
                                        .currentThread().getName()));
                        // 其它线程中新建一个handler
                        Looper.prepare();// 
创建该线程的Looper对象,用于接收消息,在非主线程中是没有looper的所以在创建handler前一定要使用prepare()创建一个Looper
                        myThreadHandler = new Handler() {
                                public void handleMessage(android.os.Message msg) {
                                        Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler handleMessage run...", Thread
                                                        .currentThread().getName()));
                                }
                        };
                      
  Looper.myLooper().loop();//建立一个消息循环,该线程不会退出
                }
        }

   现在,你应该对Handler的机制有所了解了吧,若有什么疑问,欢迎在评论中提出

  在其它线程中Handler使用主线程的Looper

   前面我说了在新线程中要新建一个Handler需要调用Looper.prepare();也有另一种方法就是使用主线程中的Looper,那就不必新建Looper对象了:

                        threadMainLoopHandler =new Handler(Looper.getMainLooper()){
                                public void handleMessage(android.os.Message msg) {
                                        Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--threadMainLoopHandler handleMessage run...", Thread
                                                        .currentThread().getName()));                                        
                                }
                                //该handleMessage方法将在mainthread中执行
                        };

  这时候注意不要在handleMessage做太多的操作,因为它在主线程中执行,会影响主线程执行ui更新操作。

    使用Message.callback回调

   public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
从dispatchMessage定义可以看出,如果Message对象自带callback对象,handler不会执行handleMessage方法而是执行message.callback中定义的run方法,当然callback还是在handler关联的looper所绑定的线程中执行的。实际上Handler.post(Runnable r)方法就是把r添加到一个msg.callback的,也就是说,下面两种写法,没有什么区别:

1.使用Message.callback

 

2.使用Handler.post

 

注:对于Handler机制相关测试,我写了一个测试类:

http://download.csdn.net/source/3275970

3.Handler对Activity finish影响。

在开发的过程中碰到一个棘手的问题,调用Activity.finish函数Acitivity没有执行生命周期的ondestory函数,后面查找半天是因为有一个handler成员,因为它有一个delay消息没有处理,调用Activity.finish,Activity不会马上destory,所以记得在Ativity finish前清理一下handle中的未处理的消息,这样Activity才会顺利的destory

  1. myThreadHandler.post(new Runnable() {  
  2.                       
  3.                     @Override  
  4.                     public void run() {  
  5.                         Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run",  
  6.                                 Thread.currentThread().getName()));   
  7.                     }  
  8.                 });  

 

  1. Message msg = Message.obtain(myThreadHandler,new Runnable() {  
  2.       
  3.     @Override  
  4.     public void run() {  
  5.         Log.d(Constant.TAG, MessageFormat.format("Thread[{0}]--myThreadHandler.Message.callback.run",  
  6.                 Thread.currentThread().getName()));   
  7.     }  
  8. });  
  9. myThreadHandler.sendMessage(msg);  

 

分享到:
评论

相关推荐

    模拟Android Handler机制Demo

    【Android Handler机制】是Android应用程序中用于线程间通信的核心组件,它与Looper和Message紧密配合,实现消息的发送、处理以及线程间的同步。在Android应用开发中,尤其是涉及到UI更新时,Handler机制显得尤为...

    Android Handler机制的工作原理详析

    Android Handler机制的工作原理详析 Android Handler机制是Android系统中的一种消息机制,负责处理应用程序中的消息处理和线程之间的通信。Handler机制的工作原理可以分为以下几个部分:Looper、MessageQueue、...

    Android Handler机制解析

    Android Handler机制解析 Android Handler机制是Android系统中的一种机制,用于处理线程之间的通信和消息传递。在Android系统中,Handler机制是基于Java的线程机制来实现的。下面将对Android Handler机制进行详细的...

    android handler 机制 源码

    在这里,我们将深入探讨Android Handler机制的源码,了解其工作原理。 首先,`Handler`类是处理消息的核心组件。它通过`post()`或`sendMessage()`方法接收并分发Message对象。当创建一个Handler实例时,通常会与...

    Android Handler机制实例

    本文将深入探讨Android Handler机制的实例,帮助初学者理解并掌握这一核心概念。 首先,我们要理解Android应用的基本运行环境。Android应用程序主要在主线程(UI线程)中运行,执行所有的用户交互和界面更新。然而...

    详解Android Handler 机制 (一)用法全解

    ps:这是关于Android Handler 机制的第一篇文章,主要来说一下Handler的用法,本文尽量归纳完全,如有缺漏,欢迎补充。 Handler的主要作用是切换线程,以及隐式的充当接口回调的作用,当子线程网络请求结束后,通过...

    Android Handler 机制实现原理分析

    Android Handler机制是Android异步消息处理的核心,它用于在主线程和子线程之间进行通信,确保UI更新在主线程中执行。以下是对Handler机制实现原理的详细解析: 1. **Handler**: Handler类是消息处理的中心,它有两...

    handler机制

    Android Handler机制是Android异步消息处理的核心组成部分,它与Looper和Message紧密关联,共同构建了一个线程间的通信桥梁。在Android应用开发中,尤其是UI更新和长时间运行的任务处理,Handler机制扮演了至关重要...

    使用C++11实现Android系统的Handler机制

    使用C++11实现Android系统的Handler机制 Handler机制是Android系统中的一种跨线程通讯机制,它可以让不同线程之间进行数据交换和通讯。这个机制主要包含三个部分:Handler、Looper和Message Queue。 Handler是...

    Android Handler线程间的调度

    Android Handler机制就是解决线程间通信和调度的关键工具。这篇博客"Android Handler线程间的调度"深入探讨了如何利用Handler来实现不同线程之间的交互。 Handler是Android中的一个关键组件,它与Looper和Message...

    android handler

    ### Android Handler机制详解 #### 一、概述 在Android开发中,`Handler`是一个非常重要的概念,它主要用于解决UI线程和其他线程之间的通信问题。本文将深入探讨Android中的`Handler`机制及其与线程、`Looper`以及...

    Android的Handler机制实现原理分析

    先上图,让大家好理解下handler机制:handler机制示例图上面一共出现了几种类,ActivityThread,Handler,MessageQueue,Looper,msg(Message),对这些类作简要介绍:ActivityThread:程序的启动入口,为什么要介绍...

    Android_Handler消息处理机制

    在Android系统中,Handler、Message和Looper构成了一个关键的异步通信机制,即Handler消息处理机制。这个机制允许Android应用程序在不同的线程间传递消息,处理UI更新等操作,是多线程编程中的重要组成部分。下面...

    androidHandler测试的demo

    在“androidHandler测试的demo”中,我们可以预期包含以下内容: 1. 创建自定义`Handler`子类:这个子类可能重写了`handleMessage(Message msg)`方法,根据`msg.what`的值执行不同的操作,比如更新UI元素或执行特定...

    java 手写实现 Android Handle 机制

    Android中的Handler机制是Android消息处理和线程通信的核心机制,它允许开发者在不同的线程间传递消息并执行相应的操作。本篇文章将详细讲解如何使用Java手写实现Android的Handler机制,以及背后的原理。 首先,...

    android多线程handler/message机制详解

    Android 多线程Handler/Message机制详解 Android 多线程机制是 Android 应用程序中最重要的组件之一,它允许应用程序在后台执行一些操作,而不影响用户的交互体验。在 Android 中,多线程机制是基于 Handler 和 ...

    Android Handler传值的demo

    在Android开发中,`Handler`、`Message`和`Looper`是实现线程间通信的重要机制,特别是当需要在主线程(UI线程)和工作线程之间传递数据时。本示例“Android Handler传值的demo”将帮助我们深入理解这一机制。 `...

Global site tag (gtag.js) - Google Analytics