zoukankan      html  css  js  c++  java
  • 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的缩写。arg1和arg2是Android提供的所谓low-cost的变量,只是一般也就是用来设置一些int值。

    d)data參数,data參数是一个Bundle类型的对象,我们能够通过setData方法来设置bundle。就跟我们在Activity之间利用Intent传递数据一样来使用。

    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 post(Runnable r)
        {
           return  sendMessageDelayed(getPostMessage(r), 0);
        }
    
        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);
        }

    而事实上,不管是还是sendMessage还是使用post方法,事实上终于都是通过调用sendMessageAtTime方法,将相应的Message对象放入一个MessageQueue中的。

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

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

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

    结束。

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    Educational Codeforces Round 88 (Rated for Div. 2) D. Yet Another Yet Another Task(枚举/最大连续子序列)
    Educational Codeforces Round 88 (Rated for Div. 2) A. Berland Poker(数学)
    Educational Codeforces Round 88 (Rated for Div. 2) E. Modular Stability(数论)
    Educational Codeforces Round 88 (Rated for Div. 2) C. Mixing Water(数学/二分)
    Codeforces Round #644 (Div. 3)
    Educational Codeforces Round 76 (Rated for Div. 2)
    Educational Codeforces Round 77 (Rated for Div. 2)
    Educational Codeforces Round 87 (Rated for Div. 2)
    AtCoder Beginner Contest 168
    Codeforces Round #643 (Div. 2)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4675373.html
Copyright © 2011-2022 走看看