Android之什么时候调用onSaveInstance方法的时候(为什么按Home键盘会调用,按Back不调用)
2017-04-18 00:51
627 查看
1、函数介绍
1)、onCreate(Bundle savedInstanceState) 方法
Activity 创建时回调 : 该方法会自动传入一个 Bundle 对象, 该 Bundle 对象就是上次被系统销毁时在 onSaveInstanceState 或者 onRestoreInstanceState 中保存的数据-- 注意 : 只有是系统自动回收的时候才会保存 Bundle 对象数据;
-- Bundle 对象来源 : onCreate() 方法中的 Bundle 对象参数, 是在 onSaveInstance() 或者 onRestoreInstanceState() 方法中保存的 Bundle 对象;
2)、 onSaveInstanceState(Bundle outState) 方法
onSaveInstanceState函数是Activity的生命周期函数outState 参数作用 :
数据保存 : Activity 声明周期结束的时候, 需要保存 Activity 状态的时候, 会将要保存的数据使用键值对的形式 保存在 Bundle 对象中;
恢复数据 : 在 Activity 的 onCreate()方法 创建 Activity 的时候会传入一个 Bundle 对象, 这个 Bundle 对象就是这个 outState 参数;
调用时机 : Activity 容易被销毁的时候调用, 注意是容易被销毁, 也可能没有销毁就调用了;
按下Home键 : Activity 进入了后台, 此时会调用该方法;
按下电源键 : 屏幕关闭, Activity 进入后台;
启动其它 Activity : Activity 被压入了任务栈的栈底;
横竖屏切换 : 会销毁当前 Activity 并重新创建;
onSaveInstanceState方法调用注意事项 :
用户主动销毁不会调用 : 当用户点击回退键 或者 调用了 finish() 方法, 不会调用该方法;
调用时机不固定 : 该方法一定是在 onStop() 方法之前调用, 但是不确定是在 onPause() 方法之前 还是 之后调用;
布局中组件状态存储 : 每个组件都 实现了 onSaveInstance() 方法, 在调用函数的时候, 会自动保存组件的状态, 注意, 只有有 id 的组件才会保存;
关于默认的 super.onSaveInstanceState(outState) : 该默认的方法是实现 组件状态保存的;
(3) onRestoreInstanceState(Bundle savedInstanceState) 方法
方法回调时机 : 在 Activity 被系统销毁之后 恢复 Activity 时被调用, 只有销毁了之后重建的时候才调用, 如果内存充足, 系统没有销毁这个 Activity, 就不需要调用;-- Bundle 对象传递 : 该方法保存的 Bundle 对象在 Activity 恢复的时候也会通过参数传递到 onCreate() 方法中;
2、源码分析调用onSaveInstance函数的时候
1)、看下ActivityThread.handlePauseActivity的源码private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { ActivityClientRecord r = mActivities.get(token); if (r != null) { //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); if (userLeaving) { performUserLeavingActivity(r); } r.activity.mConfigChangeFlags |= configChanges; performPauseActivity(token, finished, r.isPreHoneycomb()); // Make sure any pending writes are now committed. if (r.isPreHoneycomb()) { QueuedWork.waitToFinish(); } // Tell the activity manager we have paused. if (!dontReport) { try { ActivityManagerNative.getDefault().activityPaused(token); } catch (RemoteException ex) { } } mSomeActivitiesChanged = true; } }
再看performPauseActivity方法
final Bundle performPauseActivity(IBinder token, boolean finished, boolean saveState) { ActivityClientRecord r = mActivities.get(token); return r != null ? performPauseActivity(r, finished, saveState) : null; }
再看掉用重载方法performPauseActivity
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState) { ... if (!r.activity.mFinished && saveState) { callCallActivityOnSaveInstanceState(r); } ... }我们知道调用callCallActivityOnSaveInstanceState方法,看名称发现这里应该回调的是Activity的onSaveInstanceState方法,我们再看掉用这个函数的条件
!r.activity.mFinished && saveState如果activity没有掉用finish()
方法,mFinished的值就是false,如果需要进入这个函数,就需要后面的值saveState值为0,这里的saveState是performPauseActivity方法传递过来的
performPauseActivity(token, finished, r.isPreHoneycomb());我们再看函数r.isPreHoneycomb
public boolean isPreHoneycomb() { if (activity != null) { return activity.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB; } return false; }App设置的targetSdk版本号小于android
versionCode 11也就是android3.0的时候返回为true,其他的时候返回为false,也就是说当我们App设置的targetVersion大于android3.0的时候才会执行callCallActivityOnSaveInstanceState方法,然后接着看callCallActivityOnSaveInstanceState方法,如下
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) { r.state = new Bundle(); r.state.setAllowFds(false); if (r.isPersistable()) { r.persistentState = new PersistableBundle(); mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state); } }我们再去Instrumentation.java里面去看函数callActivityOnSaveInstanceState
public void callActivityOnSaveInstanceState(Activity activity, Bundle outState, PersistableBundle outPersistentState) { activity.performSaveInstanceState(outState, outPersistentState); }我们再去Activity.java里面去看函数performSaveInstanceState实现
final void performSaveInstanceState(Bundle outState) { onSaveInstanceState(outState); saveManagedDialogs(outState); mActivityTransitionState.saveState(outState); if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState); }可以看到这里掉用了Activity的onSaveInstanceState方法,这样经过一系列的方法回调之后就执行了onSaveInstanceState方法。
接下来我们看下onStop方法是否会执行onSaveInstanceState方法,同理Actvitiy执行onStop方法会回调ActivityThread的handleStopActivity
接下来我们看handleStopActivity方法的实现:
private void handleStopActivity(IBinder token, boolean show, int configChanges) { ActivityClientRecord r = mActivities.get(token); r.activity.mConfigChangeFlags |= configChanges; StopInfo info = new StopInfo(); performStopActivityInner(r, info, show, true); if (localLOGV) Slog.v( TAG, "Finishing stop of " + r + ": show=" + show + " win=" + r.window); updateVisibility(r, show); info.activity = r; info.state = r.state; info.persistentState = r.persistentState; mH.post(info); mSomeActivitiesChanged = true; }我们再来看方法performStopActivityInner实现
private void performStopActivityInner(ActivityClientRecord r, StopInfo info, boolean keepShown, boolean saveState) { // Next have the activity save its current state and managed dialogs... if (!r.activity.mFinished && saveState) { if (r.state == null) { callCallActivityOnSaveInstanceState(r); } } if (!keepShown) { try { // Now we are idle. r.activity.performStop(); } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException( "Unable to stop activity " + r.intent.getComponent().toShortString() + ": " + e.toString(), e); } } r.stopped = true; }
我们知道saveState穿进去为true,只要mFinished不是true就一定进入这个方法,所以只要在mFinished不为true,也就是没有调用finish()函数的前提下,就一定执行onSaveInstanceState方法,所以当App设置的targetVersion大于android3.0,没有调用finish函数的情况下,一定会调用onSaveInstanceState方法后再去调用onStop方法。
3、为什么按Home键盘会掉用onSaveInstance方法保存数据,按Back不掉用onSaveInstance方法保存数据
因为按下Home键盘没有调用 finish函数,如果targetVersion大于Androi3.0就一定执行onSaveInstanceState方法,所以就保存数据了,如果按下返回键,会调用 finish方法,所有mFinished为true,所以不会掉用onSaveInstanceState方法,所以不会保存数据。
4、手机常见操作Activity生命周期状态变化来验证
写了一个简单的Activity,在每个Activity周期函数里面打印了相关的执行函数信息1)、启动Activity
2)、按下电源或者Home键
3)、按亮电源键或者点击项目(一开启按了Home键)
4)、按下返回键(back键盘)
5、总结
1、onSaveInstanceState方法是Activity的生命周期方法,主要用于在Activity销毁时保存一些信息。2、当Activity只执行onPause方法时(Activity a打开一个透明Activity b)这时候如果App设置的targetVersion大于android3.0则不会执行onSaveInstanceState方法。
3、当Activity执行onStop方法时,通过分析源码我们知道只要Activity没有执行finish函数一定会调用onSaveInstanceState的方法,然后再去掉用onStop方法。
onPause() -> onSaveInstanceState() -> onStop()
相关文章推荐
- android中onSaveInstanceState和onRestoreInstanceState什么时候被调用
- android onSaveInstanceState方法 横坚屏切换
- onSaveInstanceState() 什么时候调用
- Android翻译】关于Activity的onSaveInstanceState调用时机的说明
- Android Activity的onSaveInstanceState() 和 onRestoreInstanceState()方法
- Android中用onSaveInstanceState保存Fragment状态的方法
- Android BaseSavedState 以及 Activity onSaveInstanceState 和 onRestoreInstanceState 方法使用注意事项
- android onSaveInstanceState 方法
- 【Android翻译】关于Activity的onSaveInstanceState调用时机的说明
- Android Activity的onSaveInstanceState() 和 onRestoreInstanceState()方法
- [转]android onSaveInstanceState方法
- 【Android翻译】关于Activity的onSaveInstanceState调用时机的说明
- android onSaveInstanceState方法
- android onSaveInstanceState的使用方法
- android_onSaveInstanceState的调用
- activity 中的 onSaveInstanceState方法的调用时机
- android onSaveInstanceState的使用方法
- Android开发之Activity的onSaveInstanceState()和 onRestoreInstanceState()方法
- android onSaveInstanceState方法
- (转载)-- android onSaveInstanceState方法