设为首页 加入收藏

TOP

Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复(四)
2017-10-13 10:12:11 】 浏览:6473
Tags:Android Fragment 使用 Activity WebView 状态 保存 恢复
get(index); fragment.setInitialSavedState(savedState); }

注意这里用了SparseArray来存储Fragment的状态, 并且加上了@State, 这样在Activity重建的时候其中的内容也能够被恢复.

Back stack中的fragment

有一点很特殊的是, 当Fragment从back stack中返回, 实际上是经历了一次View的销毁和重建, 但是它本身并没有被重建.
即View状态需要重建, 实例状态不需要重建.

举个例子说明这种情形: Fragment被另一个Fragment replace(), 并且压入back stack中, 此时它的View是被销毁的, 但是它本身并没有被销毁.
也即, 它走到了onDestroyView(), 却没有走onDestroy()onDetact().
等back回来的时候, 它的view会被重建, 重新从onCreateView()开始走生命周期.
在这整个过程中, 该Fragment中的成员变量是保持不变的, 只有View会被重新创建.
在这个过程中, instance state的saving并没有发生.

所以, 很多时候Fragment还需要考虑的是在没有Activity帮助的情形下(Activity并没有可能重建的情形), 自身View状态的保存.
此时要注意一些不容易发现的错误, 比如List的新实例需要重新setAdapter等.

Fragment setRetainInstance

Fragment有一个相关方法:
setRetainInstance
这个方法设置为true的时候表示, 即便activity重建了, 但是fragment的实例并不被重建.
注意此方法只对没有放在back stack中的fragment生效.
什么时候要用这个方法呢? 处理configuration change的时候:
Handling Configuration Changes with Fragments
这样, 当屏幕旋转, Activity重建, 但是其中的fragment和fragment正在执行的任务不必重建.
更多解释可以参见:
http://stackoverflow.com/questions/11182180/understanding-fragments-setretaininstanceboolean
http://stackoverflow.com/questions/11160412/why-use-fragmentsetretaininstanceboolean

注意这个方法只是针对configuration change, 并不影响用户主动关闭和系统销毁的情况:
当activity被用户主动finish, 其中的所有fragments仍然会被销毁.
当activity不在最顶端, memory不够了, 系统仍然可能会销毁activity和其中的fragments.

View的状态保存和恢复

View的状态保存和恢复主要是依赖于下面几个方法:
保存: saveHierarchyState() -> dispatchSaveInstanceState() -> onSaveInstanceState()
恢复: restoreHierarchyState() -> dispatchRestoreInstanceState() -> onRestoreInstanceState()
还有两个重要的前提条件是View要有id, 并且setSavedEnabled()为true.(这个值默认为true).
在系统的widget里(比如TextView, EditText, Checkbox等), 这些都是已经被处理好的, 我们只需要给View赋予id, Activity和Fragment重建的时候会自动恢复其中的状态. (这里的Fragment恢复对应入口一和入口三, 入口二属于跨实例新建的情况).

但是如果你要使用第三方的自定义View, 就需要确认一下它们内部是否有状态保存和恢复的代码.
如果不行你就需要继承该自定义View, 然后实现这两个方法:

//
// Assumes that SomeSmartButton is a 3rd Party view that
// View State Saving/Restoring are not implemented internally
//
public class SomeBetterSmartButton extends SomeSmartButton {

    ...

    @Override
    public Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        // Save current View's state here
        return bundle;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        // Restore View's state here
    }

    ...

}

WebView的状态保存和恢复

WebView的状态保存和恢复不像其他原生View一样是自动完成的.
WebView不是继承自View的.
如果我们把WebView放在布局里, 不加处理, 那么Activity或Fragment重建的过程中, WebView的状态就会丢失, 变成初始状态.

在Fragment的onSaveInstanceState()里面可以加入如下代码来保存WebView的状态:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    webView.saveState(outState);
}

然后在初始化的时候, 增加判断, 不必每次都打开初始链接:

if (savedInstanceState != null) {
    webView.restoreState(savedInstanceState);
} else {
    webView.loadUrl(TEST_URL);
}

这样处理以后, 在重新建立的时候, WebView的状态就能恢复到离开前的页面.
不论WebView是放在Activity里还是Fragment里, 这个方法都适用.

但是Fragment还有另一种情况, 即Fragment被压入back stack, 此时它没有被destroy(), 所以没有调用onSavedInstanceState()这个方法.
这种情况返回的时候, 会从onCreateView()开始, 并且savedInstanceState为null, 于是其中WebView之前的状态在此时丢失了.
解决这种情况可以利用Fragment实例并未销毁的条件, 增加一个成员变量bundle, 保存WebView的状态, 最终解决如下:

private Bundle webViewState;

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    sup
首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java 策略模式和状态模式 下一篇Android Fragment使用(三) Activi..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目