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分私有程式和全域性程式,私有程式的名稱前面有冒號,全域性程式沒有,like this:
為了節省系統記憶體,在退出該Activity的時候可以將其殺掉(如果沒有人為殺掉該程式,在程式完全退出時該程式會被系統殺掉),like this:
使用多程式會遇到的一些問題:
斷點除錯
除錯就是跟蹤程式執行過程中的堆疊資訊,正如前面所講,每個程式都有自己獨立的資源和記憶體空間,每個程式的堆疊資訊也是獨立的,如果要在不同的程式間除錯,是實現不了的,不過可以通過如下兩種方式進行除錯:
除錯的時候去掉AndroidManifest.xml檔案中Activity的android:process標籤,這樣保證除錯狀態下是在同一程式中,堆疊資訊是連貫的,在除錯完成後記得復原該屬性;
通過列印進行除錯,但這種效率比較低。
Activity管理:
通常我們為了完全退出一個應用,會在Application裡面實現ActivityLifecycleCallbacks介面,監聽Activity的生命週期,通過LinkedList來管理所有的Activity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
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或者檔案操作來實現。
結語
通過多程式可以分擔應用內主程式的壓力,但這是下下策,最好的解決方案還是要做好效能優化。