详细讲解Android中的Message的源码
相信大家對于Android中的Handler是在為熟悉不過了,但是要知道,Handler就其本身而言只是一個殼子,真正在內部起到作用的是Message這個類,對于Message這個類,相信大家也不會陌生,正如大家經常用到的Message.obtain()的方法一樣。但是大家又是否知道obtain()方法里面為我們做了哪些操作了,下面我就帶領大家進行Message的王國,去一探究竟吧。
首先映入眼簾的是這樣的一行代碼:
?
?| 1 | 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++; ????????????} ????????} ????} |
?
?| 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> |
?
Ok,Message的內核源碼的剖析就講解到這里,相信大家以后再用到這個類的時候會有更深的理解啦。
?
結伴旅游,一個免費的交友網站:www.jieberu.com
推推族,免費得門票,游景區:www.tuituizu.com
轉載于:https://www.cnblogs.com/rabbit-bunny/p/4200381.html
總結
以上是生活随笔為你收集整理的详细讲解Android中的Message的源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hash散列算法解析
- 下一篇: 股票买进卖出时间间隔 还要注意这几点