Android中應(yīng)用多進(jìn)程的整理總結(jié)
前言
在計(jì)算機(jī)操作系統(tǒng)中,進(jìn)程是進(jìn)行資源分配和調(diào)度的基本單位。這對于基于Linux內(nèi)核的Android系統(tǒng)也不例外。在Android的設(shè)計(jì)中,一個(gè)應(yīng)用默認(rèn)有一個(gè)(主)進(jìn)程。但是我們通過配置可以實(shí)現(xiàn)一個(gè)應(yīng)用對應(yīng)多個(gè)進(jìn)程。
本文將試圖對于Android中應(yīng)用多進(jìn)程做一些整理總結(jié)。
android:process
- 應(yīng)用實(shí)現(xiàn)多進(jìn)程需要依賴于
android:process這個(gè)屬性 - 適用元素:Application, Activity, BroadcastReceiver, Service, ContentProvider。
- 通常情況下,這個(gè)屬性的值應(yīng)該是”:“開頭。表示這個(gè)進(jìn)程是應(yīng)用私有的。無法在在跨應(yīng)用之間共用。
- 如果該屬性值以小寫字母開頭,表示這個(gè)進(jìn)程為全局進(jìn)程??梢员欢鄠€(gè)應(yīng)用共用。(文章結(jié)尾會探討這個(gè)問題)
一個(gè)應(yīng)用 android:process 簡單示例
<activity android:name=".MusicPlayerActivity" android:process=":music"/> <activity android:name=".AnotherActivity" android:process="droidyue.com"/>
應(yīng)用多進(jìn)程有什么好處
增加App可用內(nèi)存
在Android中,默認(rèn)情況下系統(tǒng)會為每個(gè)App分配一定大小的內(nèi)存。比如從最早的16M到后面的32M或者48M等。具體的內(nèi)存大小取決于硬件和系統(tǒng)版本。
這些有限的內(nèi)存對于普通的App還算是夠用,但是對于展示大量圖片的應(yīng)用來說,顯得實(shí)在是捉襟見肘。
仔細(xì)研究一下,你會發(fā)現(xiàn)原來系統(tǒng)的這個(gè)限制是作用于進(jìn)程的(畢竟進(jìn)程是作為資源分配的基本單位)。意思就是說,如果一個(gè)應(yīng)用實(shí)現(xiàn)多個(gè)進(jìn)程,那么這個(gè)應(yīng)用可以獲得更多的內(nèi)存。
于是,增加App可用內(nèi)存成了應(yīng)用多進(jìn)程的重要原因。
獨(dú)立于主進(jìn)程
除了增加App可用內(nèi)存之外,確保使用多進(jìn)程,可以獨(dú)立于主進(jìn)程,確保某些任務(wù)的執(zhí)行和完成。
舉一個(gè)簡單的例子,之前的一個(gè)項(xiàng)目存在退出的功能,其具體實(shí)現(xiàn)為殺掉進(jìn)程。為了保證某些統(tǒng)計(jì)數(shù)據(jù)上報(bào)正常,不受當(dāng)前進(jìn)程退出的影響,我們可以使用獨(dú)立的進(jìn)程來完成。
多進(jìn)程的不足與缺點(diǎn)
數(shù)據(jù)共享問題
- 由于處于不同的進(jìn)程導(dǎo)致了數(shù)據(jù)無法共享內(nèi)容,無論是static變量還是單例模式的實(shí)現(xiàn)。
- SharedPreferences 還沒有增加對多進(jìn)程的支持。
- 跨進(jìn)程共享數(shù)據(jù)可以通過Intent,Messenger,AIDL等。
SQLite容易被鎖
- 由于每個(gè)進(jìn)程可能會使用各自的SQLOpenHelper實(shí)例,如果兩個(gè)進(jìn)程同時(shí)對數(shù)據(jù)庫操作,則會發(fā)生SQLiteDatabaseLockedException等異常。
- 解決方法:可以使用ContentProvider來實(shí)現(xiàn)或者使用其他存儲方式。
不必要的初始化
- 多進(jìn)程之后,每個(gè)進(jìn)程在創(chuàng)建的時(shí)候,都會執(zhí)行自己的
Application.onCreate方法。 - 通常情況下,onCreate中包含了我們很多業(yè)務(wù)相關(guān)的初始化,更重要的這其中沒有做按照進(jìn)程按需初始化,即每個(gè)進(jìn)程都會執(zhí)行全部的初始化。
- 按需初始化需要根據(jù)當(dāng)前進(jìn)程名稱,進(jìn)行最小需要的業(yè)務(wù)初始化。
- 按需初始化可以選擇簡單的if else判斷,也可以結(jié)合工廠模式
一些簡單的代碼示例
獲取當(dāng)前的進(jìn)程名
private String getCurrentProcessName() {
String currentProcName = "";
int pid = android.os.Process.myPid();
ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
currentProcName = processInfo.processName;
break;
}
}
return currentProcName;
}
基本的進(jìn)程初始化類
這個(gè)類用來每個(gè)進(jìn)程共用的業(yè)務(wù)初始化邏輯。
public class AppInitialization {
@CallSuper
public void onAppCreate(Application application) {
Log.i("AppInitialization", "onAppCreate is being executed.");
}
}
工廠模式的應(yīng)用
public class AppInitFactory {
public static AppInitialization getAppInitialization(String processName) {
AppInitialization appInitialization;
if (processName.endsWith(":game")) {
appInitialization = new GameAppInitialization();
} else if (processName.endsWith(":music")) {
appInitialization = new MusicAppInitialization();
} else {
appInitialization = new AppInitialization();
}
return appInitialization;
}
static class GameAppInitialization extends AppInitialization {
@Override
public void onAppCreate(Application application) {
super.onAppCreate(application);
Log.i("GameAppInitialization", "onAppCreate is being executed.");
}
}
static class MusicAppInitialization extends AppInitialization {
@Override
public void onAppCreate(Application application) {
super.onAppCreate(application);
Log.i("MusicAppInitialization", "onAppCreate is being executed.");
}
}
}
具體的調(diào)用時(shí)的代碼
public class MyApplication extends Application{
private static final String LOGTAG = "MyApplication";
@Override
public void onCreate() {
super.onCreate();
String currentProcessName = getCurrentProcessName();
Log.i(LOGTAG, "onCreate currentProcessName=" + currentProcessName);
AppInitialization appInitialization = AppInitFactory.getAppInitialization(currentProcessName);
if (appInitialization != null) {
appInitialization.onAppCreate(this);
}
}
}
是否需要多進(jìn)程
判斷是否需要多進(jìn)程,需要視具體情況而定。
內(nèi)存限制
- 研究內(nèi)存占用居高不下的原因
- 如果是由內(nèi)存泄漏導(dǎo)致,嘗試解決來降低內(nèi)存占用
- 如有必要,可以通過配置largeHeap嘗試解決
除了內(nèi)存限制之外,還需要考慮是否真的需要獨(dú)立于主進(jìn)程來執(zhí)行某些操作。
關(guān)于android:process的其他問題
在android:process部分我們提到,如果這個(gè)屬性值以小寫字母開頭,那么就是全局的進(jìn)程,可以被其他應(yīng)用共用。
所謂的共用,指的是不同的App的組件運(yùn)行在同一個(gè)指定的進(jìn)程中。
準(zhǔn)備條件
受制于Android系統(tǒng)的安全機(jī)制,我們需要做到以下兩個(gè)準(zhǔn)備條件才可以。
- 這個(gè)應(yīng)用使用同樣的簽名
- 兩個(gè)應(yīng)用指定同一個(gè)
android:sharedUserId的值
具體示例
第一個(gè)App的Manifest文件,AnotherActivity運(yùn)行在名為droidyue.com的進(jìn)程中。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.droidyue.androidmutipleprocesssample" android:sharedUserId="droidyue.com" > <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".AnotherActivity" android:process="droidyue.com"/> </application> </manifest>
第二個(gè)App的Manifest文件,SecondActivity運(yùn)行在名為droidyue.com的進(jìn)程中。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.jishuxiaoheiwu.accessfromanotherprocess" android:sharedUserId="droidyue.com" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".SecondActivity" android:process="droidyue.com" /> </application> </manifest>
上面的AnotherActivity和SecondActivity會運(yùn)行在一個(gè)名為droidyue.com的進(jìn)程中,盡管他們位于不同的App中。
但是這種共用進(jìn)程的方式會引發(fā)很多問題,不太建議大家使用。
以上就是我關(guān)于Android中多進(jìn)程的一些淺顯的研究,如有問題,歡迎指正。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
- Android應(yīng)用開發(fā)SharedPreferences存儲數(shù)據(jù)的使用方法
- Android 動畫之TranslateAnimation應(yīng)用詳解
- Android 動畫之ScaleAnimation應(yīng)用詳解
- Android開發(fā)中多進(jìn)程共享數(shù)據(jù)簡析
- Android 多進(jìn)程資料總結(jié)
- Android 進(jìn)程間通信實(shí)現(xiàn)原理分析
- Android應(yīng)用程序四大組件之使用AIDL如何實(shí)現(xiàn)跨進(jìn)程調(diào)用Service
- Android編程防止進(jìn)程被第三方軟件殺死的方法
- 解析后臺進(jìn)程對Android性能影響的詳解
- Android結(jié)束進(jìn)程的方法詳解
相關(guān)文章
Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解及實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解的相關(guān)資料,并附實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11
Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度
本篇文章主要介紹了Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android App數(shù)據(jù)格式Json解析方法和常見問題
JSON數(shù)據(jù)格式,在Android中被廣泛運(yùn)用于客戶端和網(wǎng)絡(luò)(或者說服務(wù)器)通信,非常有必要系統(tǒng)的了解學(xué)習(xí)。恰逢本人最近對json做了一個(gè)簡單的學(xué)習(xí),特此總結(jié)一下,以饗各位2014-03-03
Andriod arcgis保存Mapview為圖片的實(shí)例代碼
這篇文章主要介紹了Andriod arcgis保存Mapview為圖片的實(shí)例代碼 的相關(guān)資料,需要的朋友可以參考下2016-03-03
Android 8.0升級不跳轉(zhuǎn)應(yīng)用安裝頁面的解決方法
這篇文章主要為大家詳細(xì)介紹了Android 8.0升級不跳轉(zhuǎn)應(yīng)用安裝頁面的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06
Android Java實(shí)現(xiàn)余弦匹配算法示例代碼
這篇文章主要介紹了Android Java實(shí)現(xiàn)余弦匹配算法示例代碼的相關(guān)資料,這里通過java 算法實(shí)現(xiàn)余弦匹配算法實(shí)現(xiàn)比較的實(shí)例,需要的朋友可以參考下2016-11-11

