Android應用內多進程介紹及使用
一個應用默認只有一個進程,這個進程(主進程)的名稱就是應用的包名,進程是系統分配資源和調度的基本單位,每個進程都有自己獨立的資源和內存空間,其它進程不能任意訪問當前進程的內存和資源,系統給每個進程分配的內存會有限制。
如果一個進程佔用內存超過了這個內存限制,就會報OOM的問題,很多涉及到大圖片的頻繁操作或者需要讀取一大段數據在內存中使用時,很容易報OOM的問題,如果此時在程序中人爲地使用GC會嚴重影響程序運行的流暢性,並且有時候並沒有什麼卵用,多數時候我們可以在android:minSdkVersion=”11”及以上的應用中,給AndroidManifest.xml的Application標籤增加”android:largeHeap=”true”“這句話,請求系統給該應用分配更多可申請的內存
但是這種做法的弊端有:
-
有時候並不能徹底解決問題,比如API Level小於11時,或者是應用需要的內存比largeHeap分配的更大的時候;
當該應用在後臺時,仍然佔用着的內存,系統總的內存就那麼多,如果每個應用都向系統申請更多的內存,會影響整機運行效率。 -
爲了徹底地解決應用內存的問題,Android引入了多進程的概念,它允許在同一個應用內,爲了分擔主進程的壓力,將佔用內存的某些頁面單獨開一個進程,比如Flash、視頻播放頁面,頻繁繪製的頁面等。Android多進程使用很簡單,只需要在AndroidManifest.xml的聲明四大組件的標籤中增加”android:process”屬性即可,process分私有進程和全局進程,私有進程的名稱前面有冒號,全局進程沒有
爲了節省系統內存,在退出該Activity的時候可以將其殺掉(如果沒有人爲殺掉該進程,在程序完全退出時該進程會被系統殺掉),like this:
使用多進程會遇到的一些問題:
斷點調試
調試就是跟蹤程序運行過程中的堆棧信息,正如前面所講,每個進程都有自己獨立的資源和內存空間,每個進程的堆棧信息也是獨立的,如果要在不同的進程間調試,是實現不了的,不過可以通過如下兩種方式進行調試:
調試的時候去掉AndroidManifest.xml文件中Activity的android:process標籤,這樣保證調試狀態下是在同一進程中,堆棧信息是連貫的,在調試完成後記得復原該屬性;
通過打印進行調試,但這種效率比較低。
Activity管理:
通常我們爲了完全退出一個應用,會在Application裏面實現ActivityLifecycleCallbacks接口,監聽Activity的生命週期,通過LinkedList來管理所有的Activity:
public class TestApplication extends Application implements ActivityLifecycleCallbacks{ @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(this); } @Override public void onActivityCreated(Activity activity, Bundle arg1) { if (null != mExistedActivitys && null != activity) { // 把新的 activity 添加到最前面,和系統的 activity 堆棧保持一致 mExistedActivitys.offerFirst(new ActivityInfo(activity,ActivityInfo.STATE_CREATE)); } } @Override public void onActivityDestroyed(Activity activity) { if (null != mExistedActivitys && null != activity) { ActivityInfo info = findActivityInfo(activity); if (null != info) { mExistedActivitys.remove(info); } } } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } public void exitAllActivity() { if (null != mExistedActivitys) { // 先暫停監聽(省得同時在2個地方操作列表) unregisterActivityLifecycleCallbacks( this ); // 彈出的時候從頭開始彈,和系統的 activity 堆棧保持一致 for (ActivityInfo info : mExistedActivitys) { if (null == info || null == info.mActivity) { continue; } try { info.mActivity.finish(); } catch (Exception e) { e.printStackTrace(); } } mExistedActivitys.clear(); // 退出完之後再添加監聽 registerActivityLifecycleCallbacks( this ); } } private ActivityInfo findActivityInfo(Activity activity) { if (null == activity || null == mExistedActivitys) { return null; } for (ActivityInfo info : mExistedActivitys) { if (null == info) { continue; } if (activity.equals(info.mActivity)) { return info; } } return null; } class ActivityInfo { private final static int STATE_NONE = 0; private final static int STATE_CREATE = 1; Activity mActivity; int mState; ActivityInfo() { mActivity = null; mState = STATE_NONE; } ActivityInfo(Activity activity, int state) { mActivity = activity; mState = state; } } private LinkedList<ActivityInfo> mExistedActivitys = new LinkedList<ActivityInfo>(); }
但是如果應用內有多個進程,每創建一個進程就會跑一次Application的onCreate方法,每個進程內存都是獨立的,所以通過這種方式無法實現將應用的Activity放在同一個LinkedList中,不能實現完全退出一個應用。
內存共享:
不同進程之間內存不能共享,最大的弊端是他們之間通信麻煩,不能將公用數據放在Application中,堆棧信息、文件操作也是獨立的,如果他們之間傳遞的數據不大並且是可序列化的,可以考慮通過Bundle傳遞, 如果數據量較大,則需要通過AIDL或者文件操作來實現。
結語
通過多進程可以分擔應用內主進程的壓力,但這是下下策,最好的解決方案還是要做好性能優化。