引用:http://www.linuxidc.com/Linux/2012-01/51332.htm
當我們從Home點選ShortCut圖示啟動一個應用程式後,這個應用程式打開了很多個Activity,假設順序為A,B,C,然後我們按Home鍵,再次從桌面用圖示啟動這個應用程式,我們會發現顯示的是剛才的C,而不是A。這裡我們普遍的想法是按Home鍵是讓程式退到背景,然後讓桌面顯示出來。那麼我們就來看看Home鍵到底是怎麼回事。
在Framework中我們找到源碼,我們首先在interceptKeyBeforeDispatching這個方法中找到Home按鍵代碼如下
[java]
// If the HOME button is currently being held, then we do special
// chording with it.
if (mHomePressed) {
// If we have released the home key, and didn't do anything else
// while it was pressed, then it is time to go home!
if (keyCode == KeyEvent.KEYCODE_HOME) {
if (!down) {
mHomePressed = false;
if (!canceled) {
// If an incoming call is ringing, HOME is totally disabled.
// (The user is already on the InCallScreen at this point,
// and his ONLY options are to answer or reject the call.)
boolean incomingRinging = false;
try {
ITelephony phoneServ = getPhoneInterface();
if (phoneServ != null) {
incomingRinging = phoneServ.isRinging();
} else {
Log.w(TAG, "Unable to find ITelephony interface");
}
} catch (RemoteException ex) {
Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
}
if (incomingRinging) {
Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
} else {
launchHomeFromHotKey();
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
}
}
return true;
}
這裡就是按Home鍵時執行的方法我們找到
launchHomeFromHotKey();
/**
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
if (mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
});
} else {
// no keyguard stuff to worry about, just launch home!
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
再進入startDockOrHome();
void startDockOrHome() {
Intent dock = createHomeDockIntent();
if (dock != null) {
try {
mContext.startActivity(dock);
return;
} catch (ActivityNotFoundException e) {
mContext.startActivity(mHomeIntent);
}
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
這段代碼是在init()方法中,對mHomeIntent的初始化,這個Intent就是跳轉到Launcher程式中的配置了 <category android:name="android.intent.category.HOME" />這個屬性的Launcher Activity,另外我們還看到兩個flag
FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
newTask保證了我們回到之前Launcher所在的棧,reset task if need是設定清理棧标志,保證清除掉該棧除Launcher以外其他activity(在Launcher清單檔案中我們還看到android:clearTaskOnLaunch="true"這個屬性,後面會描述),這樣我們的Launcher當然會在自己單獨的Task中,而且android:launchMode="singleTask"這個屬性保證不會啟動一個新的Launcher。
通過Launcher啟動的其他Activity不會跑到Launcher所在的Task中(後面的文章會提到Launcher啟動activity的過程)。是以按Home鍵是打開了Launcher這個activity并且保證他在自己單獨的Task中,其他的activity進入stop狀态。
另外Launcher中打開一個activity直接進入之前打開的Task 而不是新打開一個activity.