(自以為)優(yōu)雅的跨進(jìn)程單例的實(shí)現(xiàn)思路

零 燙燙燙燙燙燙

單例模式糯而,也叫單子模式账嚎,是一種常用的軟件設(shè)計(jì)模式涂身。在應(yīng)用這個(gè)模式時(shí)雄卷,單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)的全局對(duì)象蛤售,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為丁鹉。

但這種設(shè)計(jì)模式有局限:只能在一個(gè)進(jìn)程內(nèi)生效。但項(xiàng)目開發(fā)中又難免會(huì)出現(xiàn)開啟多個(gè)進(jìn)程的情況悴能。這個(gè)時(shí)候揣钦,原本設(shè)計(jì)的單例,在整個(gè)應(yīng)用的范圍來(lái)看漠酿,變成了兩個(gè)單例冯凹。兩個(gè)進(jìn)程內(nèi)的單例的內(nèi)部狀態(tài)(變量的取值)也就無(wú)法同步了,這也是這個(gè)問題的核心(單例的行為(方法)在不同進(jìn)程是一致的炒嘲,內(nèi)部狀態(tài)會(huì)影響到行為的結(jié)果)宇姚。

轉(zhuǎn)載請(qǐng)注明原帖地址:http://sr1.me/think-when-god-laugh/2016/03/22/across-process-singleton-implement.html

一 如何解決

解決數(shù)據(jù)不同步問題的方法很多,簡(jiǎn)單的做法有兩種:持久化或者跨進(jìn)程調(diào)用摸吠。

1 持久化

Android可用的持久化的方式有本地文件空凸、SharedPreference和數(shù)據(jù)庫(kù)這幾種。

通過將數(shù)據(jù)持久化到本地寸痢,數(shù)據(jù)讀寫都通過操作持久化數(shù)據(jù),可以實(shí)現(xiàn)數(shù)據(jù)的同步紊选。

這種方案會(huì)引入新的問題:同時(shí)寫文件的問題(數(shù)據(jù)可能會(huì)亂掉)啼止,同時(shí)會(huì)增加讀寫本地IO的耗費(fèi)。

在以上三種持久化方式里兵罢,本地文件献烦、SharedPreference都有可能出現(xiàn)同時(shí)寫文件的問題。數(shù)據(jù)庫(kù)還好卖词,而且Android組件里有ContentProvider可以幫助我們簡(jiǎn)化一些操作巩那。

但這三種方法,都要額外做一些事情此蜈,比如數(shù)據(jù)存儲(chǔ)格式(本地文件)即横、字段名的定義和維護(hù)(SharedPreference)、表的定義和維護(hù)和增刪改查的實(shí)現(xiàn)(數(shù)據(jù)庫(kù))裆赵。光想一想就很頭大东囚。

最開始有想過ContentProvider的方式實(shí)現(xiàn),但實(shí)現(xiàn)起來(lái)也挺麻煩挺蛋疼的战授,后來(lái)就不了了之了页藻。

2 IPC(進(jìn)程間調(diào)用)

IPC機(jī)制很適合用于解決這個(gè)問題桨嫁,這個(gè)實(shí)現(xiàn)方式更接近后端的RPC(遠(yuǎn)程過程調(diào)用)。Android的進(jìn)程間通訊機(jī)制采用AIDL來(lái)實(shí)現(xiàn)份帐。

這種實(shí)現(xiàn)方式的方法步驟也不算簡(jiǎn)單:

  1. 定義AIDL接口
  2. 實(shí)現(xiàn)AIDL接口里的方法
  3. 實(shí)現(xiàn)一個(gè)Service璃吧,在綁定的時(shí)候返回實(shí)現(xiàn)了AIDL接口Binder對(duì)象(被調(diào)用方)
  4. 綁定Service,獲得Binder對(duì)象废境,通過Binder對(duì)象進(jìn)行方法調(diào)用(調(diào)用方)

雖然不簡(jiǎn)單肚逸,但也不復(fù)雜。但怎么應(yīng)用到現(xiàn)有代碼里呢彬坏?

依舊是最簡(jiǎn)單的解決思路:

  1. 為每個(gè)單例的調(diào)用都封裝一層(實(shí)際是兩層朦促,一層給業(yè)務(wù),一層是AIDL栓始,用于跨進(jìn)程調(diào)用)
  2. 在調(diào)用的時(shí)候务冕,封裝層里判斷當(dāng)前調(diào)用的執(zhí)行環(huán)境,如果在單例所在的進(jìn)程幻赚,則調(diào)用單例的對(duì)應(yīng)方法禀忆,否則,發(fā)起一次進(jìn)程間調(diào)用落恼。

這個(gè)解決思路里箩退,大部分是體力活:

  1. 把單例里定義的方法添加到AIDL文件里
  2. 實(shí)現(xiàn)AIDL文件里的方法(跨進(jìn)程調(diào)用的封裝)
  3. 添加封裝層(if (在單例的進(jìn)程) { 調(diào)用單例的方法; } else { 發(fā)起跨進(jìn)程調(diào)用; })
  4. 修改原有業(yè)務(wù)的調(diào)用代碼,把它改為封裝層的調(diào)用

(我們不生產(chǎn)代碼佳谦,我們只是代碼的搬運(yùn)工)

3 完(卒)

(╯‵□′)╯︵┻━┻

(╯‵□′)╯︵┻━┻

(╯‵□′)╯︵┻━┻

(╯‵□′)╯︵┻━┻

(╯‵□′)╯︵┻━┻

(╯‵□′)╯︵┻━┻

為什么要這樣對(duì)我(抱頭痛哭)

為什么要這樣對(duì)我(抱頭痛哭)

為什么要這樣對(duì)我(抱頭痛哭)

為什么要這樣對(duì)我(抱頭痛哭)

為什么要這樣對(duì)我(抱頭痛哭)

為什么要這樣對(duì)我(抱頭痛哭)

難道就沒有更簡(jiǎn)單的方式了嗎戴涝?!

難道就沒有更簡(jiǎn)單的方式了嗎钻蔑?啥刻!

難道就沒有更簡(jiǎn)單的方式了嗎?咪笑!

難道就沒有更簡(jiǎn)單的方式了嗎可帽?!

難道就沒有更簡(jiǎn)單的方式了嗎窗怒?映跟!

難道就沒有更簡(jiǎn)單的方式了嗎?扬虚!

二 你說(shuō)你要更簡(jiǎn)單的?

讓我們來(lái)審視下上面的方案的實(shí)現(xiàn)步驟:

  1. 定義AIDL接口
  2. 實(shí)現(xiàn)AIDL接口里的方法
  3. 實(shí)現(xiàn)一個(gè)Service努隙,在綁定的時(shí)候返回實(shí)現(xiàn)了AIDL接口Binder對(duì)象(被調(diào)用方)
  4. 綁定Service,獲得Binder對(duì)象孔轴,通過Binder對(duì)象進(jìn)行方法調(diào)用(調(diào)用方)

1 簡(jiǎn)化封裝層

慢著剃法!

既然我們都需要實(shí)現(xiàn)AIDL接口了,為什么不把單例的實(shí)現(xiàn)和AIDL接口的實(shí)現(xiàn)整合起來(lái)?

也就是說(shuō):通過這種方式實(shí)現(xiàn)的單例的實(shí)例贷洲,是一個(gè)可以用于跨進(jìn)程傳輸?shù)膶?duì)象收厨!

進(jìn)一步說(shuō):我們可以在綁定的時(shí)候,把這個(gè)單例(Binder)返回优构,其他進(jìn)程只有得到這個(gè)Binder(RPC里的Proxy)诵叁,就能操作到我們這個(gè)單例了,而這個(gè)單例也就成為了我們應(yīng)用程序范疇內(nèi)所需要的單例钦椭。

想到了這一點(diǎn)拧额,我們的封裝層就可以廢掉了。80%的體力活瞬間蒸發(fā)彪腔!

2 簡(jiǎn)化綁定處理過程

剩下的20%的體力活就變成了:

  1. 定義AIDL接口侥锦,用單例對(duì)象實(shí)現(xiàn)這個(gè)AIDL接口
  2. 使用到這個(gè)單例的都要執(zhí)行一次綁定,綁定成功后德挣,作為單例的實(shí)例保存下來(lái)即可恭垦。

第一點(diǎn)怎么都省不了了。但第二點(diǎn)呢格嗅?看起來(lái)是重復(fù)性很強(qiáng)的編碼過程呢:

  1. 修改Service實(shí)現(xiàn)番挺,返回實(shí)現(xiàn)了AIDL的單例
  2. onServiceConnected里,把得到的單例的代理屯掖,設(shè)為本進(jìn)程的單例對(duì)象

如果能一次性就把所有的單例都傳遞過來(lái)玄柏,不就能少掉多次綁定調(diào)用,同時(shí)還統(tǒng)一了入口和出口贴铜。

寫過AIDL的一定會(huì)跟另一個(gè)類打交道:Parcelable粪摘。Parcelable的實(shí)現(xiàn)需要需要我們處理數(shù)據(jù)的序列化和反序列化。在這里我們的入口和出口能實(shí)現(xiàn)統(tǒng)一阀湿,同時(shí)赶熟,Parcel對(duì)象還有兩個(gè)重要的方法:writeStrongInterfacereadStrongBinder,這兩個(gè)方法實(shí)現(xiàn)了Binder對(duì)象的序列化和反序列化操作陷嘴。

因此我們可以在這里把所有的單例通過writeStrongInterface序列化,傳遞到另一個(gè)進(jìn)程间坐,另一個(gè)進(jìn)程再進(jìn)行readStrongBinder灾挨,把對(duì)應(yīng)的代理給取出來(lái),并放置到單例里竹宋。

這樣以來(lái)劳澄,我們的綁定處理過程就得到了簡(jiǎn)化。

3 Word is cheap, show me the code

GayHub提交地址蜈七,基本框架和使用Sample

3.1 核心

說(shuō)完了以上那么多秒拔,其實(shí)也就兩個(gè)關(guān)鍵點(diǎn):

  1. 單例對(duì)象實(shí)現(xiàn)AIDL接口,以支持跨進(jìn)程
  2. Parcelable里統(tǒng)一序列化(Stub)和反序列化(Proxy)單例對(duì)象

3.2 實(shí)例-單例

這里假定有以下幾個(gè)單例:

SingletonA(A表示是在A進(jìn)程)
SingletonA.aidl是它的AIDL接口飒硅;
SingletonAImp.java是這個(gè)單例的實(shí)現(xiàn)砂缩。

SingletonB(B表示是在B進(jìn)程)
SingletonB.aidl是它的AIDL接口作谚;
SingletonBImp.java是這個(gè)單例的實(shí)現(xiàn)。

SingletonC(C表示是在C進(jìn)程)
SingletonC.aidl是它的AIDL接口庵芭;
SingletonCImp.java是這個(gè)單例的實(shí)現(xiàn)妹懒。

獲取他們的實(shí)例的方法統(tǒng)一為靜態(tài)方法getInstance,代碼如下双吆,這里也是單例實(shí)現(xiàn)中唯一需要判斷所處進(jìn)程的地方:

public static synchronized SingletonA getInstance() {
    if (ProcessUtils.isProcessA()) {
        if (INSTANCE == null) {
            INSTANCE = new SingletonAImp();
        }
        return INSTANCE;
    } else {
        if (INSTANCE == null) {
            /** 自發(fā)重連 */
            Intent intent = new Intent(
                App.getContext(), ServiceA.class);
            App.getContext().bindService(intent, 
                new InstanceReceiver(), 
                Context.BIND_AUTO_CREATE);
        }
        return INSTANCE;
    }
}

這個(gè)getInstance跟傳統(tǒng)的單例不一樣眨唬,它可能返回為空。

這里面有兩個(gè)東西需要我們注意:

  1. ServiceA.class
  2. InstanceReceiver

3.3 實(shí)例-Service

ServiceA.class是A進(jìn)程提供單例給其他進(jìn)程的服務(wù)的類好乐,每個(gè)進(jìn)程都需要有一個(gè)(這樣別的進(jìn)程才能綁定過來(lái))匾竿。所以在這個(gè)例子,會(huì)有ServiceB.class蔚万,ServiceC.class岭妖,這幾個(gè)類的實(shí)現(xiàn)都是一樣的,因此這里他們其實(shí)只是簡(jiǎn)單的繼承了一個(gè)基類BaseService笛坦,并沒有做其他改動(dòng)区转,需要派生出來(lái)的原因是需要在AndroidManifest.xml里為不同進(jìn)程指定一個(gè)Service。

代碼如下:

public class BaseService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new InstanceTransferImp();
    }
}

public class ServiceA extends BaseService {}

public class ServiceB extends BaseService {}

public class ServiceC extends BaseService {}

3.4 實(shí)例-InstanceReceiver

InstanceReceiver.class是一個(gè)ServiceConnection的實(shí)現(xiàn)版扩,這里把接收到的Binder對(duì)象轉(zhuǎn)為一個(gè)InstanceTransfer废离,也就是封裝的一個(gè)AIDL對(duì)象,這個(gè)對(duì)象的作用是把我們的單例傳輸過來(lái)礁芦。

代碼:

@Override
public void onServiceConnected(ComponentName name, IBinder service){
    Log.i(TAG, "[onServiceConnected]" + name);
    try {
        /** 調(diào)用這句就會(huì)將單例(代理)實(shí)例傳遞過來(lái)了 */
        InstanceTransfer.Stub.asInterface(service).transfer();
    } catch (Exception e) {
        Log.e(TAG, "[onServiceConnected][exception when transfer instance]" + name, e);
    }
}

@Override
public void onServiceDisconnected(ComponentName name) {
    /** 意外斷開綁定的情況,這里可以重寫成發(fā)起重連 */
    Log.e(TAG, "[onServiceDisconnected][exception when service disconnected]" + name);
}

InstanceTransfer的定義:

interface InstanceTransfer {
    InstanceCarrier transfer();
}

3.5 InstanceCarrier

這里冒出了一個(gè)InstanceCarrier蜻韭,這個(gè)InstanceCarrier實(shí)際上就是我們定義的一個(gè)Parcelable類,這個(gè)類干的事情柿扣,就是前面提到的:統(tǒng)一序列化(Stub)和反序列化(Proxy)單例對(duì)象肖方。

代碼大概是這樣的:

private static final String TAG = "InstanceCarrier";

private static final int PROCESS_A = 1;
private static final int PROCESS_B = 2;
private static final int PROCESS_C = 3;

/**
 * 在這里把單例轉(zhuǎn)成IBinder傳輸?shù)狡渌M(jìn)程
 * @param dest
 * @param flags
 */
@Override
public void writeToParcel(Parcel dest, int flags) {

    if (ProcessUtils.isProcessA()) {
        dest.writeInt(PROCESS_A);
        dest.writeStrongInterface(SingletonAImp.getInstance());
        Log.i(TAG, String.format(
                    "[write][PROCESS_A][processCode=%s]", PROCESS_A));
    }else if (ProcessUtils.isProcessB()) {
        dest.writeInt(PROCESS_B);
        dest.writeStrongInterface(SingletonBImp.getInstance());
        Log.i(TAG, String.format(
                    "[write][PROCESS_B][processCode=%s]", PROCESS_B));
    }else if (ProcessUtils.isProcessC()) {
        dest.writeInt(PROCESS_C);
        dest.writeStrongInterface(SingletonCImp.getInstance());
        Log.i(TAG, String.format(
                    "[write][PROCESS_C][processCode=%s]", PROCESS_C));
    }
}

/**
 * 在這里把跨進(jìn)程傳遞過來(lái)的IBinder賦值給對(duì)應(yīng)的實(shí)例
 * @param in
 */
protected InstanceCarrier(Parcel in) {

    int processCode = in.readInt();

    switch (processCode) {
        case PROCESS_A:
            SingletonAImp.INSTANCE = 
                    SingletonA.Stub.asInterface(in.readStrongBinder());
            Log.i(TAG, String.format(
                    "[read][PROCESS_A][processCode=%s]", processCode));
            break;
        case PROCESS_B:
            SingletonBImp.INSTANCE = 
                    SingletonB.Stub.asInterface(in.readStrongBinder());
            Log.i(TAG, String.format(
                    "[read][PROCESS_B][processCode=%s]", processCode));
            break;
        case PROCESS_C:
            SingletonCImp.INSTANCE = 
                    SingletonC.Stub.asInterface(in.readStrongBinder());
            Log.i(TAG, String.format(
                    "[read][PROCESS_C][processCode=%s]", processCode));
            break;
        default:
            Log.w(TAG, String.format(
                    "[unknown][processCode=%s]", processCode));
    }
}

public InstanceCarrier() {}

@Override
public int describeContents() {
    return 0;
}

public static final Creator<InstanceCarrier> CREATOR = new Creator<InstanceCarrier>() {
    @Override
    public InstanceCarrier createFromParcel(Parcel in) {
        return new InstanceCarrier(in);
    }

    @Override
    public InstanceCarrier[] newArray(int size) {
        return new InstanceCarrier[size];
    }
};

這么一套下來(lái),整個(gè)實(shí)現(xiàn)機(jī)制就搞好未状。

后續(xù)添加新的單例俯画,只需要:

  1. 定義單例的AIDL
  2. 實(shí)現(xiàn)單例
  3. 在InstanceCarrier里添加序列化和反序列化的兩行代碼
  4. 如果添加了進(jìn)程,需要在那個(gè)進(jìn)程添加一個(gè)BaseService的派生類

如果是新增接口的話司草,也就簡(jiǎn)單的修改下AIDL文件艰垂,然后實(shí)現(xiàn)新的接口。

三 存在的問題或不足

  1. 單例內(nèi)使用到的數(shù)據(jù)類型埋虹,必須支持AIDL(Android IPC通訊的要求)猜憎,對(duì)于簡(jiǎn)單的數(shù)據(jù)革砸,可以使用系統(tǒng)的Bundle對(duì)象
  2. 實(shí)現(xiàn)的調(diào)用方法的時(shí)候本缠,需要考慮到執(zhí)行的線程可能不是調(diào)用的線程(跨進(jìn)程調(diào)用的情況下是在Binder線程),因?yàn)檎{(diào)用是同步的肮疗,對(duì)返回結(jié)果沒有影響,但對(duì)于需要在主線程執(zhí)行的邏輯來(lái)說(shuō)柬讨,需要主動(dòng)異步放到主線程去崩瓤。
  3. 線程安全:這個(gè)是編寫單例的時(shí)候需要注意的問題,因?yàn)槿魏我粋€(gè)線程都能夠訪問到這個(gè)單例姐浮,使用這個(gè)方式支持跨進(jìn)程可能會(huì)放大這個(gè)問題谷遂。
  4. Android的IPC通訊機(jī)制本身的限制:Android的IPC通訊共享1M的內(nèi)存,因此需要避免傳輸大量的數(shù)據(jù)卖鲤,同時(shí)肾扰,處理邏輯也不宜很耗時(shí)(否則消費(fèi)數(shù)據(jù)不及時(shí),消費(fèi)者處理能力低于生產(chǎn)者的生產(chǎn)力蛋逾,遲早會(huì)耗光1M的內(nèi)存)集晚。、
  5. AIDL不支持方法重載(弱弱的...)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末区匣,一起剝皮案震驚了整個(gè)濱河市偷拔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌亏钩,老刑警劉巖莲绰,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異姑丑,居然都是意外死亡蛤签,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門栅哀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)震肮,“玉大人,你說(shuō)我怎么就攤上這事留拾〈辽危” “怎么了?”我有些...
    開封第一講書人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵痴柔,是天一觀的道長(zhǎng)沦偎。 經(jīng)常有香客問我,道長(zhǎng)咳蔚,這世上最難降的妖魔是什么扛施? 我笑而不...
    開封第一講書人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮屹篓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匙奴。我一直安慰自己堆巧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谍肤,像睡著了一般啦租。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荒揣,一...
    開封第一講書人閱讀 52,821評(píng)論 1 314
  • 那天篷角,我揣著相機(jī)與錄音,去河邊找鬼系任。 笑死恳蹲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的俩滥。 我是一名探鬼主播嘉蕾,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霜旧!你這毒婦竟也來(lái)了错忱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挂据,失蹤者是張志新(化名)和其女友劉穎以清,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崎逃,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掷倔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了婚脱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片今魔。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖障贸,靈堂內(nèi)的尸體忽然破棺而出错森,到底是詐尸還是另有隱情,我是刑警寧澤篮洁,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布涩维,位于F島的核電站,受9級(jí)特大地震影響袁波,放射性物質(zhì)發(fā)生泄漏瓦阐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一篷牌、第九天 我趴在偏房一處隱蔽的房頂上張望睡蟋。 院中可真熱鬧,春花似錦枷颊、人聲如沸戳杀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)信卡。三九已至隔缀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間傍菇,已是汗流浹背猾瘸。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丢习,地道東北人牵触。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像泛领,于是被迫代替她去往敵國(guó)和親荒吏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理渊鞋,服務(wù)發(fā)現(xiàn)绰更,斷路器,智...
    卡卡羅2017閱讀 134,720評(píng)論 18 139
  • 今天是端午節(jié)放假第一天锡宋,祝各位小伙伴端午快樂儡湾!今天我也給大家送個(gè)“粽子”-AIDL之進(jìn)程間共享單例。關(guān)于AIDL的...
    juexingzhe閱讀 1,788評(píng)論 0 10
  • 一执俩、Android IPC簡(jiǎn)介 IPC是Inter-Process Communication的縮寫徐钠,含義就是進(jìn)程...
    SeanMa閱讀 1,835評(píng)論 0 8
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2役首、Andro...
    隔壁老李頭閱讀 10,774評(píng)論 13 43
  • Jianwei's blog 首頁(yè) 分類 關(guān)于 歸檔 標(biāo)簽 巧用Android多進(jìn)程尝丐,微信,微博等主流App都在用...
    justCode_閱讀 5,927評(píng)論 1 23