Android Activity數(shù)據(jù)回傳的一種另類實(shí)現(xiàn)
@(八千里路云和月)
[TOC]
業(yè)務(wù)場(chǎng)景描述
ActA啟動(dòng)了ActB, ActB會(huì)對(duì)數(shù)據(jù)進(jìn)行處理, ActB里面的數(shù)據(jù)可能會(huì)在ActC里面進(jìn)行進(jìn)一步的處理, 要求: C和B都要能夠給處理結(jié)果傳遞給ActA.
可能的實(shí)現(xiàn)方案
-
startActivityForResult
對(duì)于級(jí)聯(lián)的startActivityForResult
, 我們需要設(shè)置FLAG_ACTIVITY_FORWARD_RESULT
, 具體可以參考這篇博客](https://goo.gl/seVq9k)
這個(gè)是最先想到的方案,嘗試了一下, 發(fā)現(xiàn)并不能解決問題, 原因也在Android doc 里面有說if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result
-
使用
BroadcastReceiver
來進(jìn)行通訊.
這個(gè)方案能夠解決問題, 大家很開心.
由于一開始模塊沒有使用多進(jìn)程,我們實(shí)現(xiàn)上使用了LocalBroadcast
, 之后我們使用了多進(jìn)程的方案, 然后這個(gè)LocalBroadcast
廢了, 還好更新的BoradcastReceiver
工作量也不大.使用該方案要注意
BoradcastReceiver
生命周期的管理: 使用onCreate/onDestory
來進(jìn)行管理(總感覺怪怪的...). -
使用其他進(jìn)程間通訊的方案
- Socket/LocalSocket
ActA啟動(dòng)一個(gè)ServerSocket, ActB/ActC對(duì)數(shù)據(jù)修改時(shí), 將信息寫入到Socket里面, 這樣ActA就能實(shí)時(shí)的獲取數(shù)據(jù)的變更了.
這個(gè)是典型的用牛刀, 不實(shí)用,但也是一個(gè)解決問題的思路. - Service數(shù)據(jù)同步
提供一個(gè)后臺(tái)服務(wù)(BackgroundService/BS), 數(shù)據(jù)修改時(shí), 告訴BS, ActA到BS里面進(jìn)行查詢結(jié)果.
這個(gè)實(shí)現(xiàn)起來也太重,僅做參考.
- Socket/LocalSocket
第一種方案改進(jìn)(Evolution):
對(duì)于singleTask
E1
EventBus提供了Sticky Event
能夠規(guī)避這個(gè)問題.
Sticky Events
可以先發(fā)布后訂閱的事件, 具體可以參考官方的說明Sticky Events
由于EventBus
不支持多進(jìn)程,因此, 該方案要繼續(xù)進(jìn)化.
多進(jìn)程支持 E2
由于E1 不支持多進(jìn)程, 因此 用E1+3.2(數(shù)據(jù)同步)就能夠解決問題了.
前提
應(yīng)用里面已經(jīng)有了跨進(jìn)程數(shù)據(jù)存儲(chǔ)的方案(DB)
因此我們只要實(shí)現(xiàn)數(shù)據(jù)的Cache/Retrieve就可以了.具體的實(shí)現(xiàn)如下
- 定義數(shù)據(jù)存儲(chǔ)的接口
//IRepository.java 定義數(shù)據(jù)的存取
Observable<List<StoreEventPO>> getCurrentUIEvents(String actionType);
Observable<StoreEventPO> saveUIEvent(final StoreEventPO event);
Observable<StoreEventPO> removeUIEvent(StoreEventPO event);
//StoreEventPO.java 定義要存取的事件的數(shù)據(jù)結(jié)構(gòu).
- ActB/ActC 更新數(shù)據(jù)時(shí), Cache行為事件
//Client: 事件的生產(chǎn)者 調(diào)用
saveUIAction{
...
IRepository#saveUIEvent(StoreEventPO)
...
}
- ActA Retrieve 行為事件.
//Client: 事件的消費(fèi)者
@Override
protected void onResume() {
...
checkUIEvents();
}
public void checkUIEvents() {
IRepository#getCurrentUIEvents(EVENT_TYPE_XXX).logic...
}
方案一演進(jìn)到E2就能夠解決業(yè)務(wù)場(chǎng)景的問題了, 該方案避免使用FLAG_ACTIVITY_FORWARD_RESULT
這個(gè)復(fù)雜(對(duì)結(jié)果進(jìn)行forward
)的字段
總結(jié)
遇到問題, 使用直接暴力的方式去解決, 發(fā)現(xiàn)在特殊的場(chǎng)景下(singleTask
)撂挑子,然后思考怎樣解決該特殊的場(chǎng)景, 發(fā)現(xiàn)EventBus的Sticky Events(本質(zhì)是Cached Events)能夠解決當(dāng)下問題, 又引入了新問題(cross process), 結(jié)合項(xiàng)目的具體實(shí)現(xiàn)(數(shù)據(jù)存儲(chǔ)能夠 cross process)最終演進(jìn)到能夠解決問題的方案.