如何保存和恢复android WebView';什么是WebBackForwardList?
我正在尝试使用android studio的WebView实现一个简单的web浏览器应用程序。我想将我的WebView状态(例如WebBackForwardList)保存到内部存储,并在重新启动应用程序时将其还原。我不想只加载上次访问的url,相反,我还希望在调用WebView的如何保存和恢复android WebView';什么是WebBackForwardList?,android,webview,android-webview,Android,Webview,Android Webview,我正在尝试使用android studio的WebView实现一个简单的web浏览器应用程序。我想将我的WebView状态(例如WebBackForwardList)保存到内部存储,并在重新启动应用程序时将其还原。我不想只加载上次访问的url,相反,我还希望在调用WebView的goBack()或goForward()方法时,我希望它从内部存储中恢复以前和下次访问的链接 我目前已经实现了我自己的WebView、WebViewClient和WebChromeClient,并将访问的链接作为字符串保
goBack()
或goForward()
方法时,我希望它从内部存储中恢复以前和下次访问的链接
我目前已经实现了我自己的WebView、WebViewClient和WebChromeClient,并将访问的链接作为字符串保存到内部存储器中,以便在还原时通过调用goBack()
和goForward()
的覆盖方法中的loadUrl()
来加载它们。但这使得页面加载速度比WebView自己的goBack()
和goForward()
方法慢,而且它也不会恢复滚动位置、缩放等
所以我有两个问题,
有一种方法可以通过调用copyBackForwardList()
方法来获取WebView的WebBackForwardList,但是有没有一种方法可以设置/编辑WebBackForwardList
如果没有,我如何在重启应用程序后保存和恢复它?这不是最好的解决方案,但我为这种情况实施了一种解决方法。简单地说,我正在将WebBackForwardList项目的URL从零保存到当前索引,保存到名为
backStack
的堆栈,从当前索引加上一个到最后一个索引保存到forwardStack
。然后我将这些堆栈和当前项目的URL保存到内部存储器中
重新启动应用程序时,WebView将加载当前项目URL。当用户想要返回或前进时,我首先检查WebView是否可以返回或前进。如果可以,我调用WebView的goBack()
方法。如果不能,那么我从保存到内部存储器的堆栈中弹出并加载URL
但当从backStack
加载URL时,我必须将当前WebBackForwardList的项目URL推送到forwardStack
并清除WebView历史记录。这是必要的,因为WebView将上次加载的URL保存到WebBackForwardList的最后一个索引。这会扭曲WebBackForwardList,因为我正在加载前一项
它目前运行良好,但正如我所说,这不是最好的解决方案。您应该使用restoreState
和saveState
来实现保存和恢复
class AppWebTab extents WebView{
long unique_tab_id;
public void boolean load(){
File stackpath = new File(getContext().getExternalCacheDir(), "webstack"+unique_tab_id);
if(stackpath.exists()) {
Parcel parcel = Parcel.obtain();
byte[] data = ...//read file as Byte Array
parcel.unmarshall(data, 0, data.length);
parcel.setDataPosition(0);
Bundle bundle = new Bundle();
bundle.readFromParcel(parcel);
parcel.recycle();
WebBackForwardList stacks = restoreState(bundle);
if(stacks!=null && stacks.getSize()>0) {
return true;
}
}
return false;
}
public void save(){
File stackpath = new File(getContext().getExternalCacheDir(), "webstack"+unique_tab_id);
Bundle bundle = new Bundle();
WebBackForwardList stacks = saveState(bundle);
if(stacks!=null&&stacks.getSize()>0) {
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
bundle.writeToParcel(parcel, 0);
byte[] bytes = parcel.marshall();
parcel.recycle();
...//save Byte Array Data to file
} else {
stackpath.delete();
}
}
}
由于chromium的努力,当设备离线但本地缓存可用时,保存的BackForwardList甚至可以导航
但不能直接修改WebBackForwardList。因此,如果您有多个Web视图代表一个浏览器选项卡(豪华但有时很有用),则很难将多个BackForwardList合并并保存为一个,这是一个遗憾
正如@j_um所说,系统升级和格式更改可能会导致此方法失败。经过测试,WebView(WebView\u Chromiu\u STATE
)的数据具有一定的向下兼容性,而包裹则没有
在测试中,使用Parcel存储的数据不能跨越Android版本。因此,我必须使用ObjectOutputStream
来实现我自己的序列化方法,这几乎是相同的。因此,使用ObjectOutputStream保存的数据在从Android 4.4到Android 9的更新中幸存了下来,可以通过解析成功恢复页面
必须考虑数据格式兼容性,尤其是在不同版本的android设备上同步选项卡时
现在使用这项技术+webdav服务器并安装了相同版本的webview.apk,我可以让用户从android 9->android 6共享浏览状态,反之亦然
如果webview.apk的版本不同,或者根本没有安装,那么您将遇到前向兼容性问题,网页将显示为空白(未观察到崩溃)。但是向后兼容性仍然可以。这种方式非常合理,可以正确地存储webview的状态(甚至滚动位置)。但是,如果捆绑包大小超过2048kb,应用程序将崩溃。希望有一种方法可以优化捆绑包数据,使其正常工作(我认为存储在捆绑包中的webview状态有很多东西我们不需要存储)。您不会达到这个数字。历史堆栈将自动调整到200kb左右。Parcelable
格式应该只用于IPC,而不是持久存储。任何Android更新都可能引入不兼容的更改,最好的情况下会丢失您的历史记录,最坏的情况下会导致您的应用程序抛出异常,如果您不准备捕获它,则会导致应用程序崩溃。相反,您应该在包的键上循环并自己存储每个值。它比使用地块
的代码要多,但它具有实际工作的优势。因此,Parcelable和webview的数据格式可能会更改,导致此方法失败。我想知道这次失败的可能性是否很大?失败会使我的应用程序崩溃吗?