重要和未知的知識點記錄:(知識來自於 Android開發藝術探索)
當用戶打開新的Actvity或切換當前Activity到桌面的時候,回調如下:onPause->onStop。但是這裏有一種特殊情況就是如果新activity採用了透明主體,當前Activity不會回調onStop
當activity在異常情況下發生終止,系統會調用onSaveInstanceState,他的調用時機在onStop之前,但是和onPause的調用時機沒有確定的先後順序。但是在系統重建activity的過程中,onRestoreInstanceState的調用時機在onStart之後。
在onSaveInstanceState和onRestoreInstanceState方法中,系統會自動做一些恢復動作。當activity需要被回收時,系統會自動保存activity視圖結構,並且在重建時恢復這些數據,例如用戶輸入的數據,Listview的滾動位置等,這些View的保存動作對應在相應View的onSaveInstanceState和onRestoreInstanceState方法中。
以TextView爲例:
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
// Save state if we are forced to
final boolean freezesText = getFreezesText();
boolean hasSelection = false;
int start = -1;
int end = -1;
if (mText != null) {
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
hasSelection = true;
}
}
if (freezesText || hasSelection) {
SavedState ss = new SavedState(superState);
if (freezesText) {
if (mText instanceof Spanned) {
final Spannable sp = new SpannableStringBuilder(mText);
if (mEditor != null) {
removeMisspelledSpans(sp);
sp.removeSpan(mEditor.mSuggestionRangeSpan);
}
ss.text = sp;
} else {
ss.text = mText.toString();
}
}
if (hasSelection) {
// XXX Should also save the current scroll position!
ss.selStart = start;
ss.selEnd = end;
}
if (isFocused() && start >= 0 && end >= 0) {
ss.frozenWithFocus = true;
}
ss.error = getError();
if (mEditor != null) {
ss.editorState = mEditor.saveInstanceState();
}
return ss;
}
return superState;
}
在這裏先獲取了選區位置開、結束的index和已經輸入的字符並存儲下來,以Parcelable返回給調用方。
當在onSaveInstanceState中保存了數據,並且恢復數據的時候,我們可以在onCreate或者onSaveInstanceState中拿到相應的數據,不同的是,如果activity正常啓動的話,其bundle值爲null,必須經過非空判斷,而onRestoreInstanceState則不用,只要存了數據,就一定是非空的。
針對onSaveInstanceState還有一點需要注意的是:系統只會在activity即將被銷燬並且有機會重新顯示的情況下才會去調用它。
當在manifest文件中設置了configChanges之後系統可能不會回調onSaveInstanceState和onRestoreInstanceState,但是會回調onConfigurationChanged
當使用applicationContext來啓動新的activity時,會報一個AndroidRuntimeException,因爲新啓動的activity在standard模式下會和啓動他的activity在同一個任務棧中,而applicationContext沒有任務棧,所以就會報此異常錯誤。解決這個問題的方式是爲待啓動的activity指定FLAG_ACTIVITY_NEW_TASK標誌位,這時被啓動的activity則是以singgleTask方式啓動的。