zoukankan      html  css  js  c++  java
  • Message讲解

      public final class Message implements Parcelable   

        Message实现了Parcelable的接口,也就是说经过Message封装的数据,可以通过Intent与IPC进行传输。既然实现了Parcelable接口,那么在Message方法中必不可少这三个方法:1)writeToParcel 2)describeContents 3)createFromParcel。

    下面我们需要关注的四个成员变量分别是:

    1)public int what

    2)public int arg1

    3)public int arg2

    4)public Object obj


    我们经常是用到这样的几个参数,但是其真实的含义是否真正的理解呢?只要google的内部的注释才是真正的可靠的。

    1)用户定义消息的识别码,以便于系统识别出当前的消息是关于什么的。由于每一个Handle对于自己的消息的识别码都有自己的命名空间。所以我们也就不用担心各个不同的Handler之间会存在冲突的情况。

    2)其中第二个参数与第三个参数的意义是一样的,注释上是这样说明的,这两个参数,如果用户只是需要传输简单的int类型的数据,相比较于setData(Bundle bundle),代价更低。

    3)第四个参数,按照注释上的说明,是这样理解的:这是一个发送给接受者的一个随意的数据,如果使用Messager来进行发送数据进行跨进程的通信,那么当前的obj如果实现了Parcelable就一定不能够为空指针,对于其他的数据的传输,我们一般使用setData方法就可以了。但是需要注意的是,对于高于android.os.Build.VERSION_CODES#FROYO的版本,这里的Parcelable对象是不支持的。


    上面的变量讲完了以后,接下来,我们还需要讲解另外的一组常量的定义:

    1
    2
    3
    4
    5
    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;
    //池塘里最大的尺寸
    private static final int MAX_POOL_SIZE = 50;


    乍一看,大家可能不理解上面四个变量的定义,如果我提醒一下大家,Android中的Message是可以重用的,那么相信大家就能够大致猜测到这四个变量的含义了。

    1、第一个变量其实就是充当锁的作用,避免多线程争抢资源,导致脏数据

    2、sPool这个变量可以理解为消息队列的头部的指针

    3、sPoolSize是当前的消息队列的长度

    4、定义消息队列缓存消息的最大的长度。

    Ok,到这里,Message的成员变量已经讲解完毕,接下来主要是讲解其中的Api方法。

    第一个方法就是大家经常用到的obtain方法,而且不带任何的参数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static Message obtain() {
            synchronized (sPoolSync) {
                if (sPool != null) {
                    Message m = sPool;
                    sPool = m.next;
                    m.next = null;
                    sPoolSize--;
                    return m;
                }
            }
            return new CustomMessage();
        }www.2cto.com

    首先为了避免多线程进行争抢资源,给sPoolSync进行加锁。首先判断当前的队列的指针是否为空,如果当前的指针已经不为空,当前的队列的头部的消息就是可以重用并且被取出,那么当前的队列的头指针指向当前的消息的下一个消息,也就是m.next,同时把取出的消息的尾部指针置为null,队列的长度减1.

    第二个方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static Message obtain(Message orig) {
            Message m = obtain();
            m.what = orig.what;
            m.arg1 = orig.arg1;
            m.arg2 = orig.arg2;
            m.obj = orig.obj;
            m.replyTo = orig.replyTo;
            if (orig.data != null) {
                m.data = new Bundle(orig.data);
            }
            m.target = orig.target;
            m.callback = orig.callback;
            return m;
        }

    我们可以看到,这个方法相对于上面的方法多了一个orig的参数,从上面的代码我们可以看到,首先从队列中取出Message的对象,然后对其中的参数的对象的各个数据进行逐一的拷贝,并最终返回对象。

    第三个方法如下:

    1
    2
    3
    4
    5
    public static Message obtain(Handler h) {
            Message m = obtain();
            m.target = h;
            return m;
        }

    不用多说,这个函数中为当前创建的消息指定了一个Handler对象,因为我们知道Handler是Message的最终的目的地。

    1
    2
    3
    4
    5
    6
    public static Message obtain(Handler h, Runnable callback) {
            Message m = obtain();
            m.target = h;
            m.callback = callback;
            return m;
        }

    相对于上面的方法,这里面多了一行m.callback = callback,按照注释上面的说明,当一些消息真正的被执行的时候,callback这个Runnbale方法将会被触发执行的。

    接下来有一系列的方法的逻辑是差不多的,我们取其中的一个进行讲解:

    1
    2
    3
    4
    5
    6
    7
    8
    public static Message obtain(Handler h, int what, int arg1, int arg2) {
            Message m = obtain();
            m.target = h;
            m.what = what;
            m.arg1 = arg1;
            m.arg2 = arg2;
            return m;
        }

    也就是说创建一个Message的时候,顺便可以为这个Message提供一些逻辑上需要的参数。

    消息有创建,那么就必然存在回收的概念,下面我们一起来看一下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void recycle() {
            clearForRecycle();
            synchronized (sPoolSync) {
                if (sPoolSize < MAX_POOL_SIZE) {
                    next = sPool;
                    sPool = this;
                    sPoolSize++;
                }
            }
        }
    void clearForRecycle() { flags = 0; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; when = 0; target = null; callback = null; data = null; }



    1
     

    在clearForRecycle这个函数中,是做一些回收的预处理的操作,该置为0的参数置为0,该置为null的参数置为null。在recycle的函数中,只要当前的缓存的队列的长度没有超过上限,将当前的消息添加到队列的尾部。

    下面的方法是关于实现Parcelable所需要的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public static final Parcelable.Creator<custommessage> CREATOR
                = new Parcelable.Creator<custommessage>() {
            public Message createFromParcel(Parcel source) {
                Message msg = Message.obtain();
                msg.readFromParcel(source);
                return msg;
            }
             
            public Message[] newArray(int size) {
                return new Message[size];
            }
        };
             
        public int describeContents() {
            return 0;
        }
     
        public void writeToParcel(Parcel dest, int flags) {
            if (callback != null) {
                throw new RuntimeException(
                    "Can't marshal callbacks across processes.");
            }
            dest.writeInt(what);
            dest.writeInt(arg1);
            dest.writeInt(arg2);
            if (obj != null) {
                try {
                    Parcelable p = (Parcelable)obj;
                    dest.writeInt(1);
                    dest.writeParcelable(p, flags);
                } catch (ClassCastException e) {
                    throw new RuntimeException(
                        "Can't marshal non-Parcelable objects across processes.");
                }
            } else {
                dest.writeInt(0);
            }
            dest.writeLong(when);
            dest.writeBundle(data);
            Messenger.writeMessengerOrNullToParcel(replyTo, dest);
        }
     
        private void readFromParcel(Parcel source) {
            what = source.readInt();
            arg1 = source.readInt();
            arg2 = source.readInt();
            if (source.readInt() != 0) {
                obj = source.readParcelable(getClass().getClassLoader());
            }
            when = source.readLong();
            data = source.readBundle();
            replyTo = Messenger.readMessengerOrNullFromParcel(source);
        }</custommessage></custommessage>

     

     
    转自红黑联盟的http://www.2cto.com/kf/201412/365597.html  可以结合这篇http://blog.csdn.net/coolszy/article/details/6360577
  • 相关阅读:
    Unable To Open Database After ASM Upgrade From Release 11.1 To Release 11.2
    11g Understanding Automatic Diagnostic Repository.
    How to perform Rolling UpgradeDowngrade in 11g ASM
    Oracle 11.2.0.2 Patch 说明
    Pattern Matching Metacharacters For asm_diskstring
    Steps To MigrateMove a Database From NonASM to ASM And ViceVersa
    Upgrading ASM instance from Oracle 10.1 to Oracle 10.2. (Single Instance)
    OCSSD.BIN Process is Running in a NonRAC Environment
    Steps To MigrateMove a Database From NonASM to ASM And ViceVersa
    On RAC, expdp Removes the Service Name [ID 1269319.1]
  • 原文地址:https://www.cnblogs.com/banzhuan/p/6685736.html
Copyright © 2011-2022 走看看