66

我有一个调用 Activity B 的 Activity A。在 Activity B 中,当我单击一个按钮时,会调用 finish(),然后调用 Activity B 的 onDestroy() 并返回到 Activity A。

根据android文档,在调用onDestroy之前,将调用onSaveInstanceState(Bundle bundle),我在其中执行以下操作。

@Override
    public void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);
        System.out.println("Saving webview state");
        Log.d(TAG, "In onsave");
        wv.saveState(outState);

    }

下一次从 Activity A 启动 Activity B 时,

在 oncreate() 中,我执行以下操作:

onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

if(savedInstanceState != null){
//restore webview
}else {
// code
}
}

但是,在 Activity B 中调用 onDestroy 之前,永远不会调用 onSaveInstanceState 方法。对此的任何帮助将不胜感激。

编辑:如果这是不可能的。请让我知道是否有办法存储 webview 状态

4

5 回答 5

346

我也有类似的情况。这显然是一个开发错误。我已经覆盖了错误的方法:

public void onSaveInstanceState(Bundle outState, 
                                PersistableBundle outPersistentState)

而是一个正确的:

protected void onSaveInstanceState(Bundle outState)
于 2015-11-19T11:01:53.843 回答
60

请注意,onRestoreInstanceState()在重新创建活动时调用它,但仅在以下情况下:

它被操作系统杀死了。“这种情况发生在:

  • 设备的方向发生变化(您的活动被破坏并重新创建)
  • 您面前还有另一个活动,并且在某些时候操作系统会终止您的活动以释放内存(例如)。下次您开始活动时,onRestoreInstanceState()将被调用。”

所以如果你在你的活动中并且你点击了设备上的后退按钮,你的活动就会被finish()编辑,下次你启动你的应用程序时它会再次启动(听起来像是重新创建的,不是吗?)但这次没有保存状态,因为您在点击后退按钮时故意退出它。

于 2012-10-09T05:33:48.363 回答
9

See the doc here: http://developer.android.com/reference/android/app/Activity.html

Note that it is important to save persistent data in onPause() instead of onSaveInstanceState(Bundle) because the latter is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.

The documentation of onSaveInstanceState method says,

Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.

try this:

@Override
public void onPause(){
   System.out.println("Saving webview state");
    Log.d(TAG, "In onsave");
    wv.saveState(outState);
    super.onPause();

}

and
@Override
 public void onResume(){
     //restore webview
 }

I am not sure what is the purpose of that if statement, but try this and see what happens.

于 2012-10-09T05:04:13.363 回答
3

最终,您将不得不将背景/历史记录写入持久存储。在设备被关闭作为一个例子的情况下,以及避免一个人为的(在我看来)你调用onSaveInstanceState的例子onPause(你需要做什么来获取你想要传递的包onRestoreInstanceState然后你可以传递进入restoreState)。

因此,除了重新考虑您的设计(如果用户关闭了您的应用程序并且您没有制作浏览器,他们真的想要保持相同的历史记录吗?),您应该查找SharedPreferences以及如何使用它们。

不幸的是,您不能将捆绑包放在共享首选项中,我也不建议尝试通过编写捆绑包Parcelable(它仅适用于 IPC,而不是持久存储)。但是您可以做的是存储捆绑包存储的所有原语。这也可能是人为的,但在我看来,这是获得永久存储的唯一方法。

然后通过存储在 SharedPreferences 中的原语重建你的包,并将其传递到restoreState(). 您可以检查 Android 源代码以了解webView.saveState()实际执行的操作(我查看了 2.1 代码,它似乎编写了一个 int、一个可序列化对象,然后是 SSL 证书的另一个包。SSL 证书包本身只是四个整数) . 在我的脑海中,我只写你能写的所有原语,然后存储你写序列化数据的本地文件的位置(字符串)。

即使您有整个 BackForward 列表的一些有序集合,我也不确定如何将其转换为goBack()goForward()使用这些值(有一个受保护的方法涉及将项目添加到列表中,但您无法访问它)。除非您确实使用restoreState(),这就是为什么我们将竭尽全力正确重建捆绑包的原因。

说真的,除非我的搜索技能很糟糕(完全有可能),否则将WebView历史存储在可以为您完成工作的地方saveInstanceState/restoreInstanceState似乎并不是很多人遇到的问题。即当用户明确关闭他们的应用程序时,没有很多人试图保留 WebView 历史记录,所以你必须问自己为什么要这样做?

抱歉,如果有一种非常简单的方法可以持久存储此信息并重新加载到 WebView 顺便说一句!

于 2012-10-09T07:42:24.580 回答
0

对于调用onSaveInstance方法,请使用

public void onSaveInstanceState(Bundle outState)

用于保存不需要使用的值

public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState)
于 2019-10-27T15:16:17.203 回答