若是一條進程可以擁有足夠多的資源,且不會被系統kill掉的話,讓程序運行在一條進程上是最好的選擇。可是系統資源是按進程來分配的,每條進程資源分配是有個上限的,並且當咱們的APP退到後臺以後,系統會根據系統資源使用狀況,回收部分後臺進程資源。java
具備推送或後臺播放音樂等功能的APP,在APP被退到後臺以後,爲了保持良好的用戶體驗,則須要在後臺保持運行狀態。而這些功能模塊的運行能夠脫離主程序而運行,爲了保持後臺運行,且不干預系統回收進程資源的前提下,咱們將這些功能拆分到小而獨立的進程當中。android
知足什麼條件才須要拆分獨立進程呢?git
在Android應用程序中跨進程通信是很是常見的,咱們經常使用的四大組件均支持跨進程通信。本文中咱們重點看下Service跨進程通信方式。github
Android提供的Service跨進程調用方式:框架
經過AIDL定義跨進程接口提供給業務調用是Android應用程序開發中,最爲經常使用的跨進程調用實現的方式,AIDL接口提供了同步與異步調用的支持,基本能知足全部的跨進程調用需求。異步
經過AIDL接口調用跨進程邏輯須要以下幾個步驟:ide
代碼實現須要以下幾個步驟:函數
經過Messenger調用跨進程邏輯須要以下幾個步驟:post
代碼實現須要以下幾個步驟:ui
Messenger.send(Message)
接口向遠端發出調用命令以實現跨進程調用;Android系統直接提供的AIDL和Messenger的方式存在的一些問題:
最初設計IPCInvoker就是爲了解決AIDL和Messenger存在的問題,讓跨進程調用變得更簡單。下面咱們來看看IPCInvoker是如何作跨進程調用的。
從IPCInvoker調用模型圖中,能夠看出是AIDL的一個擴展,Service端做爲Task執行的容器,而由調用者來決定Task的邏輯實現。下面一塊兒看一下IPCInvoker的簡單使用。
同步調用跨進程邏輯
public class IPCInvokeSample_InvokeByType {
private static final String TAG = "IPCInvokerSample.IPCInvokeSample_InvokeByType";
public static void invokeSync() {
Bundle bundle = new Bundle();
bundle.putString("name", "AlbieLiang");
bundle.putInt("pid", android.os.Process.myPid());
IPCString result = IPCInvoker.invokeSync(PushProcessIPCService.PROCESS_NAME,
bundle, IPCRemoteInvoke_BuildString.class);
Log.i(TAG, "invoke result : %s", result);
}
private static class IPCRemoteInvoke_BuildString implements IPCRemoteSyncInvoke<Bundle, IPCString> {
@Override
public IPCString invoke(Bundle data) {
String msg = String.format("name:%s|fromPid:%s|curPid:%s",
data.getString("name"), data.getInt("pid"), android.os.Process.myPid());
Log.i(TAG, "build String : %s", msg);
return new IPCString(msg);
}
}
}
複製代碼
IPCInvoker實現跨進程調用主要分爲兩部分:
IPCRemoteInvoke_BuildString
類中的invoke
函數的實現就是跨進程邏輯,這裏只是輸出了一行log,並把msg
做爲返回值return了;IPCString result = IPCInvoker.invokeSync(xxx)
即是跨進程調用,這裏的調用把須要在遠端進程執行的邏輯的class做爲參數傳入了IPCInvoker。看到上面示例代碼,是否是根本沒有感受到這是在寫跨進程代碼?也沒看到有鏈接Service的過程了!對的IPCInvoker設計的初衷就是讓跨進程調用變得簡單,就像Handler.post
一個Runnable同樣簡單。
若是你們進一步思考上述示例中的代碼,並對比AIDL和Messenger的跨進程實現,能夠很明顯看出IPCInvoker的跨進程實現是高內聚的,跨進程邏輯不用寫在Service裏面,這樣業務邏輯就不用與Service產生任何的耦合了,Service在IPCInvoker框架中只是一個執行遠端邏輯的容器。
下面咱們在看一下IPCInvoker異步調用跨進程邏輯代碼是如何寫的
異步調用跨進程邏輯
public class IPCInvokeSample_InvokeByType {
private static final String TAG = "IPCInvokerSample.IPCInvokeSample_InvokeByType";
public static void invokeAsync() {
Bundle bundle = new Bundle();
bundle.putString("name", "AlbieLiang");
bundle.putInt("pid", android.os.Process.myPid());
IPCInvoker.invokeAsync(PushProcessIPCService.PROCESS_NAME, bundle,
IPCRemoteInvoke_PrintSomething.class, new IPCRemoteInvokeCallback<IPCString>() {
@Override
public void onCallback(IPCString data) {
Log.i(TAG, "onCallback : %s", data.value);
}
});
}
private static class IPCRemoteInvoke_PrintSomething implements IPCRemoteAsyncInvoke<Bundle, IPCString> {
@Override
public void invoke(Bundle data, IPCRemoteInvokeCallback<IPCString> callback) {
String result = String.format("name:%s|fromPid:%s|curPid:%s",
data.getString("name"), data.getInt("pid"), android.os.Process.myPid());
callback.onCallback(new IPCString(result));
}
}
}
複製代碼
異步調用是經過調用IPCInvoker.invokeAsync
實現的,這個接口與IPCInvoker.invokeSync
相比多了一個IPCRemoteInvokeCallback
參數,IPCRemoteInvokeCallback
的onCallback函數的回調依賴遠端邏輯的主動調用,onCallback能夠被屢次調用。
上面使用的是IPCInvoker中最爲基本和最簡單的兩個接口IPCInvoker.invokeSync
和IPCInvoker.invokeAsync
,能夠很明顯看出IPCInvoker相比普通的AIDL和Messenger實現的跨進程調用更爲直觀,接口更容易使用。
IPCInvoker組件裏面還包括了幾大模塊:
到目前爲止本文還沒介紹如何接入IPCInvoker,其實IPCInvoker的接入也是很是簡單的,這裏就不展開說明了,你們能夠經過閱讀《接入IPCInvoker》來接入IPCInvoker。IPCInvoker的wiki文檔能夠到《IPCInvoker wiki》中詳細閱讀。
歡迎使用IPCInvoker,有興趣的同窗能夠一塊兒維護該項目。(項目地址爲github.com/AlbieLiang/…)