重要和未知的知识点记录:(知识来自于 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方式启动的。