Android中利用Handler实现消息的分发机制(零)

在之前一篇介绍AsyncTask的文章中,我们在最后讲到,AsyncTask是利用Handler的消息异步处理机制,将操作结果,利用Message传回主线程,从而进行UI线程的更新的。

而在我们日常的开发工作中,Handler也是我们经常使用的类之一,那么Handler的主要作用是什么?

Handler 的主要作用就是对消息(消息可以是我们想做的一些UI更新,也可以是其他的一些不可见的操作,如操作数据库等)的异步处理机制,而相信大家都了解异步的概念。

简单地说一下:

1)从程序的角度来看,就是当执行某行代码的时候,发送了一个异步请求(消息),程序不需要在此行代码上继续等待下去,而是能够继续执行之后的代码。

2)从用户的角度来看,用户发送了一个消息,不需要什么事也不做,就在那傻等,而可以去做其他的事情,当对应的消息被处理完之后 ,就会通过回调机制处理对应的结果。

所以,Android中Handler的消息异步处理机制,能够给用户提供一个更加合理及友好的用户体验。当然,Android是用Handler来实现,其他的平台环境,也有着自己的一套异步实现机制,原理一样,名称不同而已。

既然我们是做Android开发的,那么我们肯定就要好好地学习一下Handler的使用,探究一下隐藏在Handler之后的代码架构。

首先,我们还是从简单的例子来入门,学习一下,如何使用Handler。

代码如下:

public class MainActivity extends ActionBarActivity {

    private static final int MSG_ID_1 = 1;
    private static final int MSG_ID_2 = 2;

    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_ID_1:
                Log.v("Test", "Toast called from Handler.sendMessage()");
                break;
            case MSG_ID_2:
                break;
            }

        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Message message = mHandler.obtainMessage();
        message.what = MSG_ID_1;
        mHandler.sendMessage(message);
    }
}

当我们启动程序的时候,我们可以看到,在LogCat里面就会看到,已经打印出了如下的信息:

10-27 15:13:21.382: V/Test(9618): Toast called from Handler.sendMessage()

而这正是我们在handler的handleMessage中对msg.what = MSG_ID_1 的情况下进行处理的。

从这个简单的例子,我们可以归纳一下Handler的使用步骤,大概有以下几步:

1)创建一个Handler对象,并且实现其 handleMessage(Message msg) 方法,如代码中:

private Handler mHandler = new Handler() {

而实现handleMessage方法一步,我们可以看到,会获取一个Message对象。

Message对象封装了一些参数,常用的大概有以下几个:

a)what 参数:这是一个 int 值,经常是我们用来区分消息的一个ID,比如例子中,我们将MSG_ID_1在创建消息的时候赋值给msg.what。

b)obj 参数:这是一个Object对象。通过obj参数,可以把任何对象赋给消息,然后在handleMessage中进行处理,而这也是Handler在异步处理中传递数据的方法。

c)arg1, arg2 等参数:上述a),b) 两个参数是我们最常用的Message的参数了,基本上也需要这两个参数就足够了,不过Message还是提供了其他的一些字段供我们使用,如argX等,也就是 arguments的缩写。

2)当创建好Handler对象之后,第二步就需要创建一个Message对象了,创建Message对象有两种方法:

2.1)直接创建新对象,代码如下:

Message msg = new Message()

2.2)利用Handler.obtainMessage()方法,也即上面代码中使用的方式,如下:

Message message = mHandler.obtainMessage();

一般情况下,我们建议使用第二种方式,为什么呢?

因为在Message的内部中维护了一个类似消息池的对象,当我们使用Handler来对Message进行分发的时候,处理完之后,Message对象并不一定会被马上销毁,而是有可能放到一个消息池中。

当利用Handler的obtainMessage方法,Handler会去从消息池中获取一个已经存在的对象,并初始化好其信息,这样,我们就不需要再重新去创建一个对象,浪费一些内存,在嵌入式应用,内存不是很大的情况下,这是对性能的一种优化。

在创建Message的时候,我们就可以对msg.what进行赋值,目的就是为了Handler在handleMessage的时候,可以判断这个消息的用途或目的是什么。

当然,不同的需求,肯定有不同的处理,这就具体情况具体分析了。

3)当消息(Message)创建好了之后,我们就可以利用Handler的sendMessage来进行发送消息了,之后,这个消息就会被其handler所捕获,从而进行处理了。

接下来,我们就再扩充一下这个例子,代码如下:

public class MainActivity extends ActionBarActivity {

    private static final int MSG_ID_1 = 1;
    private static final int MSG_ID_2 = 2;

    private Handler mHandler = new Handler() {

        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_ID_1:
                Log.v("Test", "Toast called from Handler.sendMessage()");
                break;
            case MSG_ID_2:
                String str = (String) msg.obj;
                Log.v("Test", str);
                break;
            }

        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Message message = mHandler.obtainMessage();
        message.what = MSG_ID_1;
        mHandler.sendMessage(message);

        Message msg2 = mHandler.obtainMessage();
        msg2.obj = "I'm String from Message 2";
        msg2.what = MSG_ID_2;
        mHandler.sendMessage(msg2);
    }
}

而其对应的结果如下:

10-27 15:35:19.168: V/Test(12135): Toast called from Handler.sendMessage()
10-27 15:35:19.168: V/Test(12135): I'm String from Message 2

由此,我们可以看到,利用obj参数,我们将String对象给传到handleMessage中去了。

除了 sendMessage方法,发送消息时, Handler还可使用如下的方法:

    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendEmptyMessage(int what)
    {
        return sendEmptyMessageDelayed(what, 0);
    }

    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain();
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, 0);
    }

我们可以看到,无论是sendEmptyMessage还是sendMessage,其实最终都是通过调用sendMessageAtTime方法,将对应的Message对象放入一个MessageQueue中的。

那么其为什么要放到MessageQueue?放到MessageQueue中有如何跑回到Handler的handleMessage中的呢?

接下来的文章,我们再继续来学习。

这一篇我们就简单地介绍了如何使用Handler,简单的例子,简单地入门。

结束。

时间: 2024-10-11 16:10:25

Android中利用Handler实现消息的分发机制(零)的相关文章

Android中利用Handler实现消息的分发机制(三)

在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而如果在子线程中需要去使用Handler的时候,我们就需要显式地去调用Looper的 prepare方法和loop方法,从而为子线程创建其唯一的Looper. 具体代码如下: class LooperThread extends Thread { public Handler mHandler; public void run()

Android中利用Handler实现消息的分发机制(二)

在这篇文章开始前,我们先总结一下前两篇文章中关于Handler, Looper和MessageQueue等的一些关键点: 0)在线程中创建Handler之前,必须先调用Looper.prepare(), 创建一个线程局部变量Looper,然后调用Looper.loop() 进入轮循. 1)当Handler创建之后,就可以调用Handler的sendMessageAtTime方法发送消息,而实际上是调用MessageQueue的enqueueMessage方法,将对应的消息放入消息队列. 2)每一

Android中利用Handler实现消息的分发机制(一)

上一篇文章,我们讲到在调用Handler的sendMessage方法时,最终我们会进入到一个叫 sendMessageAtTime的方法,如下: public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMess

Android中使用Handler(消息机制)造成内存泄露的分析和解决

问题描述: Handler 内部类持有 外部类Activity的引用,如果Activity退出而Handler还有延迟处理的消息没有处理完,会导致Activity不能回收,反复如此会导致内存泄露. 解决方案: 1.onDestroy时清除消息. mHandler.removeCallbacksAndMessages(null); // 参数为null时会清除所有消息. 2.声明Handler为static并持有Activity的弱引用. public class MainActivity ext

深入源码解析Android中的Handler,Message,MessageQueue,Looper

本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文< Android中Handler的使用>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功能.但

Android中的Handler

当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放在Activity的OnCreate或是OnStart中,会导致执行过程中整个Activity无响应,如果时间过长,程序就会挂掉.Handler就是把这些功能放到一个当初的线程里执行,与Activity互不影响. 一.Handler的定义:  Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用.比如可以用handler发送一个message,然后在handler的线程中来接收.处理该消

Android中的Handler的具体用法

Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行.Android利用Handler来实现UI线程的更新的. Handler是Android中的消息发送器,其在哪个Activity中创建就属于且紧紧属于该Activity.还可以说其在哪个线程中new的,就是那个线程的Handler. Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的U

Android中的Handler机制

直接在UI线程中开启子线程来更新TextView显示的内容,运行程序我们会发现,如下错 误:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻译过来就是:只有创建这个控件的线程才能去更新该控件的内容. 所有的UI线程要去负责View的创建并且维护它,例如更新冒个TextView的显示,都必

Android中的Handler, Looper, MessageQueue和Thread

Android中的Handler, Looper, MessageQueue和Thread 前几天,和同事探讨了一下Android中的消息机制,探究了消息的发送和接收过程以及与线程之间的关系.虽然我们经常使用这些基础的东西,但对于其内部原理的了解,能使我们更加容易.合理地架构系统,并避免一些低级错误. 对于这部分的内容,将分成4小节来描述: 1.职责与关系 2.消息循环 3.线程与更新 4.几点小结 ------------------------------------------------