日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

activity 变成后台进程后被杀死_Android后台杀死系列之二:ActivityManagerService与App现场恢复机制...

發(fā)布時(shí)間:2025/4/16 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 activity 变成后台进程后被杀死_Android后台杀死系列之二:ActivityManagerService与App现场恢复机制... 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本篇是Android后臺(tái)殺死系列的第二篇,主要講解ActivityMangerService是如何恢復(fù)被后臺(tái)殺死的進(jìn)程的(基于4.3 ),在開(kāi)篇FragmentActivity及PhoneWindow后臺(tái)殺死處理機(jī)制 中,簡(jiǎn)述了后臺(tái)殺死所引起的一些常見(jiàn)問(wèn)題,還有Android系統(tǒng)控件對(duì)后臺(tái)殺死所做的一些兼容,以及onSaveInstance跟onRestoreInstance的作用于執(zhí)行時(shí)機(jī),最后說(shuō)了如何應(yīng)對(duì)后臺(tái)殺死,但是對(duì)于被后臺(tái)殺死的進(jìn)程如何恢復(fù)的并沒(méi)有講解,本篇不涉及后臺(tái)殺死,比如LowmemoryKiller機(jī)制,只講述被殺死的進(jìn)程如何恢復(fù)的。假設(shè),一個(gè)應(yīng)用被后臺(tái)殺死,再次從最近的任務(wù)列表喚起App時(shí)候,系統(tǒng)是如何處理的呢?有這么幾個(gè)問(wèn)題可能需要解決:

Android框架層(AMS)如何知道App被殺死了

App被殺前的場(chǎng)景是如何保存的

系統(tǒng)(AMS)如何恢復(fù)被殺的App

被后臺(tái)殺死的App的啟動(dòng)流程跟普通的啟動(dòng)有什么區(qū)別

Activity的恢復(fù)順序?yàn)槭裁词堑剐蚧謴?fù)

系統(tǒng)(AMS)如何知道App被殺死了

首先來(lái)看第一個(gè)問(wèn)題,系統(tǒng)如何知道Application被殺死了,Android使用了Linux的oomKiller機(jī)制,只是簡(jiǎn)單的做了個(gè)變種,采用分等級(jí)的LowmemoryKiller,但這個(gè)其實(shí)是內(nèi)核層面的,LowmemoryKiller殺死進(jìn)程后,不會(huì)像用戶空間發(fā)送通知,也就是說(shuō)框架層的ActivityMangerService無(wú)法知道App是否被殺死,但是,只有知道App或者Activity是否被殺死,AMS(ActivityMangerService)才能正確的走喚起流程,那么AMS究竟是在什么時(shí)候知道App或者Activity被后臺(tái)殺死了呢?我們先看一下從最近的任務(wù)列表進(jìn)行喚起的時(shí)候,究竟發(fā)生了什么。

從最近的任務(wù)列表或者Icon再次喚起App的流程

在系統(tǒng)源碼systemUi的包里,有個(gè)RecentActivity,這個(gè)其實(shí)就是最近的任務(wù)列表的入口,而其呈現(xiàn)界面是通過(guò)RecentsPanelView來(lái)展現(xiàn)的,點(diǎn)擊最近的App其執(zhí)行代碼如下:

publicvoid?handleOnClick(Viewview)?{

ViewHolder?holder?=?(ViewHolder)view.getTag();

TaskDescription?ad?=?holder.taskDescription;

final?Context?context?=?view.getContext();

final?ActivityManager?am?=?(ActivityManager)

context.getSystemService(Context.ACTIVITY_SERVICE);

Bitmap?bm?=?holder.thumbnailViewImageBitmap;

...

//?關(guān)鍵點(diǎn)?1??如果TaskDescription沒(méi)有被主動(dòng)關(guān)閉,正常關(guān)閉,ad.taskId就是>=0

if?(ad.taskId?>=?0)?{

//?This?isan?active?task;?it?should?just?gotothe?foreground.

am.moveTaskToFront(ad.taskId,?ActivityManager.MOVE_TASK_WITH_HOME,

opts);

}?else{

Intent?intent?=?ad.intent;

intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

|?Intent.FLAG_ACTIVITY_TASK_ON_HOME

|?Intent.FLAG_ACTIVITY_NEW_TASK);

try?{

context.startActivityAsUser(intent,?opts,

new?UserHandle(UserHandle.USER_CURRENT));

}...

}

在上面的代碼里面,有個(gè)判斷ad.taskId >= 0,如果滿足這個(gè)條件,就通過(guò)moveTaskToFront喚起APP,那么ad.taskId是如何獲取的?recent包里面有各類RecentTasksLoader,這個(gè)類就是用來(lái)加載最近任務(wù)列表的一個(gè)Loader,看一下它的源碼,主要看一下加載:

@Override

protected?Void?doInBackground(Void...?params)?{

//?We?loadintwo?stages:first,?weupdateprogresswithjust?thefirstscreenful

//?ofitems.Then,?weupdatewiththe?restofthe?items

final?intorigPri?=?Process.getThreadPriority(Process.myTid());

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

final?PackageManager?pm?=?mContext.getPackageManager();

final?ActivityManager?am?=?(ActivityManager)

mContext.getSystemService(Context.ACTIVITY_SERVICE);

final?List?recentTasks?=

am.getRecentTasks(MAX_TASKS,?ActivityManager.RECENT_IGNORE_UNAVAILABLE);

....

TaskDescription?item?=?createTaskDescription(recentInfo.id,

recentInfo.persistentId,?recentInfo.baseIntent,

recentInfo.origActivity,?recentInfo.description);

....

}

可以看到,其實(shí)就是通過(guò)ActivityManger的getRecentTasks向AMS請(qǐng)求最近的任務(wù)信息,然后通過(guò)createTaskDescription創(chuàng)建TaskDescription,這里傳遞的recentInfo.id其實(shí)就是TaskDescription的taskId,來(lái)看一下它的意義:

publicList?getRecentTasks(intmaxNum,

intflags,intuserId)?{

...

IPackageManager?pm?=?AppGlobals.getPackageManager();

final?intN?=?mRecentTasks.size();

...

for(inti=0;?i?0;?i++)?{

TaskRecord?tr?=?mRecentTasks.get(i);

if?(i?==?0

||?((flags&ActivityManager.RECENT_WITH_EXCLUDED)?!=?0)

||?(tr.intent?==?null)

||?((tr.intent.getFlags()

&Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)?==?0))?{

ActivityManager.RecentTaskInfo?rti

=?new?ActivityManager.RecentTaskInfo();

rti.id?=?tr.numActivities?>?0???tr.taskId?:?-1;

rti.persistentId?=?tr.taskId;

rti.baseIntent?=?new?Intent(

tr.intent?!=?null??tr.intent?:?tr.affinityIntent);

if?(!detailed)?{

rti.baseIntent.replaceExtras((Bundle)null);

}

可以看出RecentTaskInfo的id是由TaskRecord決定的,如果TaskRecord中numActivities > 0就去TaskRecord的Id,否則就取-1,這里的numActivities其實(shí)就是TaskRecode中記錄的ActivityRecord的數(shù)目,更具體的細(xì)節(jié)可以自行查看ActivityManagerService及ActivityStack,那么這里就容易解釋了,只要是存活的APP、或者被LowmemoryKiller殺死的APP,其AMS的ActivityRecord是完整保存的,這就是恢復(fù)的依據(jù)。RecentActivity獲取的數(shù)據(jù)其實(shí)就是AMS中的翻版,RecentActivity并不知道將要喚起的APP是否是存活的,只要TaskRecord告訴RecentActivity是存貨的,那么久直接走喚起流程,也就是通過(guò)ActivityManager的moveTaskToFront喚起App,至于后續(xù)的工作,就完全交給AMS來(lái)處理。現(xiàn)看一下到這里的流程圖:

在喚起App的時(shí)候AMS偵測(cè)App或者Activity是否被異常殺死

接著往下看moveTaskToFrontLocked,這個(gè)函數(shù)在ActivityStack中,ActivityStack主要用來(lái)管理ActivityRecord棧的,所有start的Activity都在ActivityStack中保留一個(gè)ActivityRecord,這個(gè)也是AMS管理Activity的一個(gè)依據(jù),ActivityStack最終moveTaskToFrontLocked會(huì)調(diào)用resumeTopActivityLocked來(lái)喚起Activity,AMS獲取即將resume的Activity信息的方式主要是通過(guò)ActivityRecord,它并不知道Activity本身是否存活,獲取之后,AMS知道喚醒Activity的環(huán)節(jié)才知道App或者Activity被殺死,具體看一下resumeTopActivityLocked源碼:

final?boolean?resumeTopActivityLocked(ActivityRecord?prev,?Bundle?options)?{

//?This?activity?isnow?becoming?visible.

mService.mWindowManager.setAppVisibility(next.appToken,true);

....????恢復(fù)邏輯

if?(next.app?!=null&&next.app.thread?!=null)?{

//?正常恢復(fù)

try?{

//?Deliver?allpending?results.

ArrayList?a?=?next.results;

if?(a?!=?null)?{

final?intN?=?a.size();

if?(!next.finishing?&&?N?>?0)?{

next.app.thread.scheduleSendResult(next.appToken,?a);

}

}

...

next.app.thread.scheduleResumeActivity(next.appToken,

mService.isNextTransitionForward());

...

}?catch?(Exception?e)?{

//?Whoops,?need?torestart?this?activity!

//?這里需要重啟,難道被后臺(tái)殺死,走的是異常分支嗎?????異常殺死

if?(DEBUG_STATES)?Slog.v(TAG,?"Resume?failed;?resetting?state?to?"

+?lastState?+?":?"+next);

next.state?=?lastState;

mResumedActivity?=?lastResumedActivity;

Slog.i(TAG,?"Restarting?because?process?died:?"+next);

。。。

startSpecificActivityLocked(next,true,false);

returntrue;

}

...

}

由于沒(méi)有主動(dòng)調(diào)用finish的,所以AMS并不會(huì)清理掉ActivityRecord與TaskRecord ,因此resume的時(shí)候走的就是上面的分支,可以這里會(huì)調(diào)用next.app.thread.scheduleSendResult或者next.app.thread.scheduleResumeActivity進(jìn)行喚起上一個(gè)Activity,但是如果APP或者Activity被異常殺死,那么喚起的操作一定是失敗,會(huì)拋出異常,首先假設(shè)APP整個(gè)被殺死,那么APP端同AMS通信的Binder線程也不復(fù)存在,這個(gè)時(shí)候通過(guò)Binder進(jìn)行通信就會(huì)拋出RemoteException,如此,就會(huì)走下面的catch部分,通過(guò)startSpecificActivityLocked再次將APP重建,并且將最后的Activity重建,其實(shí)你可以本地利用AIDL寫一個(gè)C/S通信,在將一端關(guān)閉,然后用另一端訪問(wèn),就會(huì)拋出RemoteException異常,如下圖:

還有一種可能,APP沒(méi)有被kill,但是Activity被Kill掉了,這個(gè)時(shí)候會(huì)怎么樣?首先,Activity的管理是一定通過(guò)AMS的,Activity的kill一定是是AMS操刀的,是有記錄的,嚴(yán)格來(lái)說(shuō),這種情況并不屬于后臺(tái)殺死,因?yàn)檫@屬于AMS正常的管理,在可控范圍,比如打開(kāi)了開(kāi)發(fā)者模式中的“不保留活動(dòng)”,這個(gè)時(shí)候,雖然會(huì)殺死Activity,但是仍然保留了ActivitRecord,所以再喚醒,或者回退的的時(shí)候仍然有跡可循,看一下ActivityStack的Destroy回調(diào)代碼,

final?boolean?destroyActivityLocked(ActivityRecord?r,

boolean?removeFromApp,?boolean?oomAdj,?String?reason)?{

...

if?(hadApp)?{

...

boolean?skipDestroy?=?false;

try?{

關(guān)鍵代碼?1

r.app.thread.scheduleDestroyActivity(r.appToken,?r.finishing,

r.configChangeFlags);

...

if?(r.finishing?&&?!skipDestroy)?{

if?(DEBUG_STATES)?Slog.v(TAG,?"Moving?to?DESTROYING:?"+?r

+?"?(destroy?requested)");

r.state?=?ActivityState.DESTROYING;

Message?msg?=?mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);

msg.obj?=?r;

mHandler.sendMessageDelayed(msg,?DESTROY_TIMEOUT);

}?else{

關(guān)鍵代碼?2

r.state?=?ActivityState.DESTROYED;

if?(DEBUG_APP)?Slog.v(TAG,?"Clearing?app?during?destroy?for?activity?"+?r);

r.app?=?null;

}

}

returnremovedFromHistory;

}

這里有兩個(gè)關(guān)鍵啊你單,1是告訴客戶端的AcvitityThread清除Activity,2是標(biāo)記如果AMS自己非正常關(guān)閉的Activity,就將ActivityRecord的state設(shè)置為ActivityState.DESTROYED,并且清空它的ProcessRecord引用:r.app = null。這里是喚醒時(shí)候的一個(gè)重要標(biāo)志,通過(guò)這里AMS就能知道Activity被自己異常關(guān)閉了,設(shè)置ActivityState.DESTROYED是為了讓避免后面的清空邏輯。

final?void?activityDestroyed(IBinder?token)?{

synchronized?(mService)?{

final?long?origId?=?Binder.clearCallingIdentity();

try?{

ActivityRecord?r?=?ActivityRecord.forToken(token);

if?(r?!=?null)?{

mHandler.removeMessages(DESTROY_TIMEOUT_MSG,?r);

}

intindex=?indexOfActivityLocked(r);

if?(index>=?0)?{

1??

if?(r.state?==?ActivityState.DESTROYING)?{

cleanUpActivityLocked(r,?true,false);

removeActivityFromHistoryLocked(r);

}

}

resumeTopActivityLocked(null);

}?finally?{

Binder.restoreCallingIdentity(origId);

}

}

}

看代碼關(guān)鍵點(diǎn)1,只有r.state == ActivityState.DESTROYING的時(shí)候,才會(huì)移除ActivityRecord,但是對(duì)于不非正常finish的Activity,其狀態(tài)是不會(huì)被設(shè)置成ActivityState.DESTROYING,是直接跳過(guò)了ActivityState.DESTROYING,被設(shè)置成了ActivityState.DESTROYED,所以不會(huì)removeActivityFromHistoryLocked,也就是保留了ActivityRecord現(xiàn)場(chǎng),好像也是依靠異常來(lái)區(qū)分是否是正常的結(jié)束掉Activity。這種情況下是如何啟動(dòng)Activity的呢? 通過(guò)上面兩點(diǎn)分析,就知道了兩個(gè)關(guān)鍵點(diǎn)

ActivityRecord沒(méi)有動(dòng)HistoryRecord列表中移除

ActivityRecord 的ProcessRecord字段被置空,r.app = null

這樣就保證了在resumeTopActivityLocked的時(shí)候,走startSpecificActivityLocked分支

final?boolean?resumeTopActivityLocked(ActivityRecord?prev,?Bundle?options)?{

...

if?(next.app?!=null&&next.app.thread?!=null)?{

...

}?else{

//?Whoops,?need?torestart?this?activity!

...

startSpecificActivityLocked(next,true,true);

}

returntrue;

}

到這里,AMS就知道了這個(gè)APP或者Activity是不是被異常殺死過(guò),從而,決定是走resume流程還是restore流程。

App被殺前的場(chǎng)景是如何保存的: 新Activity啟動(dòng)跟舊Activity的保存

App現(xiàn)場(chǎng)的保存流程相對(duì)是比較簡(jiǎn)單的,入口基本就是startActivity的時(shí)候,只要是界面的跳轉(zhuǎn)基本都牽扯到Activity的切換跟當(dāng)前Activity場(chǎng)景的保存:先畫個(gè)簡(jiǎn)單的圖形,開(kāi)偏里面講FragmentActivity的時(shí)候,簡(jiǎn)單說(shuō)了一些onSaveInstance的執(zhí)行時(shí)機(jī),這里詳細(xì)看一下AMS是如何管理這些跳轉(zhuǎn)以及場(chǎng)景保存的,模擬場(chǎng)景:Activity A 啟動(dòng)Activity B的時(shí)候,這個(gè)時(shí)候A不可見(jiàn),可能會(huì)被銷毀,需要保存A的現(xiàn)場(chǎng),這個(gè)流程是什么樣的:簡(jiǎn)述如下

ActivityA startActivity ActivityB

ActivityA pause

ActivityB create

ActivityB start

ActivityB resume

ActivityA onSaveInstance

ActivityA stop

流程大概是如下樣子:

現(xiàn)在我們通過(guò)源碼一步一步跟一下,看看AMS在新Activity啟動(dòng)跟舊Activity的保存的時(shí)候,到底做了什么:跳過(guò)簡(jiǎn)單的startActivity,直接去AMS中去看

ActivityManagerService

publicfinalintstartActivityAsUser(IApplicationThread?caller,?String?callingPackage,

Intent?intent,?String?resolvedType,?IBinder?resultTo,

String?resultWho,?intrequestCode,intstartFlags,

String?profileFile,?ParcelFileDescriptor?profileFd,?Bundle?options,?intuserId)?{

enforceNotIsolatedCaller("startActivity");

...

returnmMainStack.startActivityMayWait(caller,?-1,?callingPackage,?intent,?resolvedType,

resultTo,?resultWho,?requestCode,?startFlags,?profileFile,?profileFd,

null,null,?options,?userId);

}

ActivityStack

finalintstartActivityMayWait(IApplicationThread?caller,intcallingUid,

intres?=?startActivityLocked(caller,?intent,?resolvedType,

aInfo,?resultTo,?resultWho,?requestCode,?callingPid,?callingUid,

callingPackage,?startFlags,?options,?componentSpecified,?null);

。。。

}

這里通過(guò)startActivityMayWait啟動(dòng)新的APP,或者新Activity,這里只看簡(jiǎn)單的,至于從桌面啟動(dòng)App的流程,可以去參考更詳細(xì)的文章,比如老羅的startActivity流程,大概就是新建ActivityRecord,ProcessRecord之類,并加入AMS中相應(yīng)的堆棧等,resumeTopActivityLocked是界面切換的統(tǒng)一入口,第一次進(jìn)來(lái)的時(shí)候,由于ActivityA還在沒(méi)有pause,因此需要先暫停ActivityA,這些完成后,

ActivityStack

final?boolean?resumeTopActivityLocked(ActivityRecord?prev,?Bundle?options)?{

...

//?We?need?tostart?pausing?thecurrentactivity?so?thetopone

//?can?be?resumed...

if?(mResumedActivity?!=?null)?{

if?(next.app?!=null&&next.app.thread?!=null)?{

mService.updateLruProcessLocked(next.app,false);

}

startPausingLocked(userLeaving,?false);

returntrue;

}

....

其實(shí)這里就是暫停ActivityA,AMS通過(guò)Binder告訴ActivityThread需要暫停的ActivityA,ActivityThread完成后再通過(guò)Binder通知AMS,AMS會(huì)開(kāi)始resume ActivityB,

private?final?void?startPausingLocked(boolean?userLeaving,?boolean?uiSleeping)?{

if?(prev.app?!=?null&&?prev.app.thread?!=null)?{

...

try?{

prev.app.thread.schedulePauseActivity(prev.appToken,?prev.finishing,

userLeaving,?prev.configChangeFlags);

ActivityThread

private?void?handlePauseActivity(IBinder?token,?boolean?finished,

boolean?userLeaving,?intconfigChanges)?{

ActivityClientRecord?r?=?mActivities.get(token);

if?(r?!=?null)?{

...

performPauseActivity(token,?finished,?r.isPreHoneycomb());

...

//?Tell?the?activity?manager?we?have?paused.

try?{

ActivityManagerNative.getDefault().activityPaused(token);

}?catch?(RemoteException?ex)?{

}

}

}

AMS收到ActivityA發(fā)送過(guò)來(lái)的pause消息之后,就會(huì)喚起ActivityB,入口還是resumeTopActivityLocked,喚醒B,之后還會(huì)A給進(jìn)一步stop掉,這個(gè)時(shí)候就牽扯到現(xiàn)場(chǎng)的保存,

ActivityStack

private?final?void?completePauseLocked()?{

if?(!mService.isSleeping())?{

resumeTopActivityLocked(prev);

}?else{

...

ActivityB如何啟動(dòng)的,本文不關(guān)心,只看ActivityA如何保存現(xiàn)場(chǎng)的,ActivityB起來(lái)后,會(huì)通過(guò)ActivityStack的stopActivityLocked去stop ActivityA,

private?final?void?stopActivityLocked(ActivityRecord?r)?{

...

if?(mMainStack)?{

r.app.thread.scheduleStopActivity(r.appToken,?r.visible,?r.configChangeFlags);

...

}

回看APP端,看一下ActivityThread中的調(diào)用:首先通過(guò)callActivityOnSaveInstanceState,將現(xiàn)場(chǎng)保存到Bundle中去,

private?void?performStopActivityInner(ActivityClientRecord?r,

StopInfo?info,?boolean?keepShown,?boolean?saveState)?{

...

//?Nexthave?the?activity?save?itscurrentstateandmanaged?dialogs...

if?(!r.activity.mFinished?&&?saveState)?{

if?(r.state?==?null)?{

state?=?new?Bundle();

state.setAllowFds(false);

mInstrumentation.callActivityOnSaveInstanceState(r.activity,?state);

r.state?=?state;

。。。

}

之后,通過(guò)ActivityManagerNative.getDefault().activityStopped,通知AMS Stop動(dòng)作完成,在通知的時(shí)候,還會(huì)將保存的現(xiàn)場(chǎng)數(shù)據(jù)帶過(guò)去。

privatestaticclass?StopInfo?implements?Runnable?{

ActivityClientRecord?activity;

Bundle?state;

Bitmap?thumbnail;

CharSequence?description;

@Override?publicvoid?run()?{

//?Tell?activity?manager?we?have?been?stopped.

try?{

ActivityManagerNative.getDefault().activityStopped(

activity.token,?state,?thumbnail,?description);

}?catch?(RemoteException?ex)?{

}

}

}

通過(guò)上面流程,AMS不僅啟動(dòng)了新的Activity,同時(shí)也將上一個(gè)Activity的現(xiàn)場(chǎng)進(jìn)行了保存,及時(shí)由于種種原因上一個(gè)Actiivity被殺死,在回退,或者重新喚醒的過(guò)程中AMS也能知道如何喚起Activiyt,并恢復(fù)。

現(xiàn)在解決兩個(gè)問(wèn)題,1、如何保存現(xiàn)場(chǎng),2、AMS怎么判斷知道APP或者Activity是否被異常殺死,那么就剩下最后一個(gè)問(wèn)題了,AMS如何恢復(fù)被異常殺死的APP或者Activity呢。

整個(gè)Application被后臺(tái)殺死情況下的恢復(fù)邏輯

其實(shí)在講解AMS怎么判斷知道APP或者Activity是否被異常殺死的時(shí)候,就已經(jīng)涉及了恢復(fù)的邏輯,也知道了一旦AMS知道了APP被后臺(tái)殺死了,那就不是正常的resuem流程了,而是要重新laucher,先來(lái)看一下整個(gè)APP被干掉的會(huì)怎么處理,看resumeTopActivityLocked部分,從上面的分析已知,這種場(chǎng)景下,會(huì)因?yàn)锽inder通信拋異常走異常分支,如下:

final?boolean?resumeTopActivityLocked(ActivityRecord?prev,?Bundle?options)?{

....

if?(next.app?!=null&&next.app.thread?!=null)?{

if?(DEBUG_SWITCH)?Slog.v(TAG,?"Resume?running:?"+next);

...

try?{

...

}?catch?(Exception?e)?{

//?Whoops,?need?torestart?this?activity!

這里是知道整個(gè)app被殺死的

Slog.i(TAG,?"Restarting?because?process?died:?"+next);

next.state?=?lastState;

mResumedActivity?=?lastResumedActivity;

Slog.i(TAG,?"Restarting?because?process?died:?"+next);

startSpecificActivityLocked(next,true,false);

returntrue;

}

從上面的代碼可以知道,其實(shí)就是走startSpecificActivityLocked,這根第一次從桌面喚起APP沒(méi)多大區(qū)別,只是有一點(diǎn)需要注意,那就是這種時(shí)候啟動(dòng)的Activity是有上一次的現(xiàn)場(chǎng)數(shù)據(jù)傳遞過(guò)得去的,因?yàn)樯洗卧谕说胶笈_(tái)的時(shí)候,所有Activity界面的現(xiàn)場(chǎng)都是被保存了,并且傳遞到AMS中去的,那么這次的恢復(fù)啟動(dòng)就會(huì)將這些數(shù)據(jù)返回給ActivityThread,再來(lái)仔細(xì)看一下performLaunchActivity里面關(guān)于恢復(fù)的特殊處理代碼:

private?Activity?performLaunchActivity(ActivityClientRecord?r,?Intent?customIntent)?{

ActivityInfo?aInfo?=?r.activityInfo;

Activity?activity?=?null;

try?{

java.lang.ClassLoader?cl?=?r.packageInfo.getClassLoader();

activity?=?mInstrumentation.newActivity(

cl,?component.getClassName(),?r.intent);

StrictMode.incrementExpectedActivityCount(activity.getClass());

r.intent.setExtrasClassLoader(cl);

if?(r.state?!=?null)?{

r.state.setClassLoader(cl);

}

}?catch?(Exception?e)?{

...

}

try?{

Application?app?=?r.packageInfo.makeApplication(false,?mInstrumentation);

...

關(guān)鍵點(diǎn)?1

mInstrumentation.callActivityOnCreate(activity,?r.state);

...

r.activity?=?activity;

r.stopped?=?true;

if?(!r.activity.mFinished)?{

activity.performStart();

r.stopped?=?false;

}

關(guān)鍵點(diǎn)?1

if?(!r.activity.mFinished)?{

if?(r.state?!=?null)?{

mInstrumentation.callActivityOnRestoreInstanceState(activity,?r.state);

}

}

if?(!r.activity.mFinished)?{

activity.mCalled?=?false;

mInstrumentation.callActivityOnPostCreate(activity,?r.state);

...

}

看一下關(guān)鍵點(diǎn)1跟2,先看關(guān)鍵點(diǎn)1,mInstrumentation.callActivityOnCreate會(huì)回調(diào)Actiivyt的onCreate,這個(gè)函數(shù)里面其實(shí)主要針對(duì)FragmentActivity做一些Fragment恢復(fù)的工作,ActivityClientRecord中的r.state是AMS傳給APP用來(lái)恢復(fù)現(xiàn)場(chǎng)的,正常啟動(dòng)的時(shí)候,這些都是null。再來(lái)看關(guān)鍵點(diǎn)2 ,在r.state != null非空的時(shí)候執(zhí)行mInstrumentation.callActivityOnRestoreInstanceState,這個(gè)函數(shù)默認(rèn)主要就是針對(duì)Window做一些恢復(fù)工作,比如ViewPager恢復(fù)之前的顯示位置等,也可以用來(lái)恢復(fù)用戶保存數(shù)據(jù)。

Application沒(méi)有被后臺(tái)殺死,Activity被殺死的恢復(fù)

打開(kāi)開(kāi)發(fā)者模式”不保留活動(dòng)“,就是這種場(chǎng)景,在上面的分析中,知道,AMS主動(dòng)異常殺死Activity的時(shí)候,將AcitivityRecord的app字段置空,因此resumeTopActivityLocked同整個(gè)APP被殺死不同,會(huì)走下面的分支

final?boolean?resumeTopActivityLocked(ActivityRecord?prev,?Bundle?options)?{

...

if?(next.app?!=null&&next.app.thread?!=null)?{

...

}?else{

關(guān)鍵點(diǎn)?1?只是重啟Activity,可見(jiàn)這里其實(shí)是知道的,進(jìn)程并沒(méi)死,

//?Whoops,?need?torestart?this?activity!

startSpecificActivityLocked(next,true,true);

}

returntrue;

}

雖然不太一樣,但是同樣走startSpecificActivityLocked流程,只是不新建APP進(jìn)程,其余的都是一樣的,不再講解。到這里,我們應(yīng)該就了解了,

Android是如何在預(yù)防的情況下保存場(chǎng)景

AMS如何知道APP是否被后臺(tái)殺死

AMS如何根據(jù)ActivityStack重建APP被殺死時(shí)的場(chǎng)景

到這里ActivityManagerService恢復(fù)APP場(chǎng)景的邏輯就應(yīng)該講完了。再碎碎念一些問(wèn)題,可能是一些面試的點(diǎn)。

主動(dòng)清除最近任務(wù)跟異常殺死的區(qū)別:ActivityStack是否正常清楚

恢復(fù)的時(shí)候,為什么是倒序恢復(fù):因?yàn)檫@是ActivityStack中的HistoryRecord中棧的順序,嚴(yán)格按照AMS端來(lái)

一句話概括Android后臺(tái)殺死恢復(fù)原理:Application進(jìn)程被Kill,但現(xiàn)場(chǎng)被AMS保存,AMS能根據(jù)保存恢復(fù)Application現(xiàn)場(chǎng)

【編輯推薦】

【責(zé)任編輯:枯木 TEL:(010)68476606】

點(diǎn)贊 0

總結(jié)

以上是生活随笔為你收集整理的activity 变成后台进程后被杀死_Android后台杀死系列之二:ActivityManagerService与App现场恢复机制...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。