在FragmentPagerAdapter中防止WebView重新加载?

9
我有一个FragmentPagerAdapter,用于显示大约6个标签,所有标签都从Web服务器加载其数据。其中一个标签包含一个WebView,它从我的服务器加载图像。生成图像的服务器端成本很高,因此我想减少重新加载WebView的调用次数。对于非WebView选项卡,我已经能够保存状态(对于那些只是简单的数组),并在滑动选项卡时恢复它们。 问题:
  • 每次使用FragmentPagerAdapter向后滑动到WebView时,WebView都会重新加载,导致重新加载时间长,对我的Web服务器负载高。
考虑的解决方案:
  • 使用ViewPager.setOffscreenPageLimit()。这会强制加载更多的标签,即使它们永远不会被查看。这在我的服务器上是不必要的昂贵操作。
  • 使用WebView.saveState()WebView.restoreState()。文档已更新,明确表示显示状态不再在此处维护,因此对于此场景不再有用。
  • 将我的活动设置为:android:configChanges="keyboardHidden|orientation|screenSize"。这适用于旋转情况,但不影响ViewPager/FragmentPagerAdapter通过选项卡滑动的情况。

听起来旧的WebView.saveState()的行为会很完美...


1
首先,要找出触发重新加载的片段中的原因。 WebView 本身对分页器和片段是毫不知情的,所以某个地方的某人正在做一些事情来触发 WebView 的重新加载。然后,您可以尝试抑制此行为。 - CommonsWare
在onCreateView方法中,我有以下代码: wv = (WebView) view.findViewById(R.id.radarWebView); if(savedInstanceState != null) { wv.restoreState(savedInstanceState); } else { wv.loadUrl(myURL); } - RealCasually
1
最主要的是,根据我的理解,向左或向右滑动会导致Fragment被销毁。当它重新出现时,它会尝试恢复状态,但由于WebView无法恢复显示状态,所以必须重新加载(这是我所能理解的最好的解释)。 - RealCasually
1
主要是我理解的,如果不使用FragmentPagerAdapter,滑动会导致片段被销毁。 FragmentPagerAdapter是“PagerAdapter的实现,将每个页面表示为片段,并将其作为用户可以返回到该页面而持久保存在片段管理器中的片段。” “在onCreateView中,我有以下内容” - 您确定每次滑动时都会调用onCreateView(),即使是以前查看过的页面吗? - CommonsWare
我知道当选项卡超过setOffscreenPageLimit()的限制时,onResume和onCreateView会被调用一次。 - RealCasually
1个回答

13
问题似乎是你在清除自己的结果。
尽管在配置更改时需要一个新的 WebView,但在其他情况下不需要一个新的 WebView。而且,如果你已经有了 WebView,你不必告诉它做任何事情。
所以,我建议你这样做:
  • 将在onCreateView()中创建的 WebView 保存在片段的数据成员中。
  • 仅当该数据成员为null时才在onCreateView()中填充布局。
  • 只有在填充布局后才调用loadUrl()
(如果你是在Java代码中创建WebView,请将“填充布局”替换为“通过其构造函数创建WebView”)。
如果片段的内容超过了WebView,你还需要将你填充的根视图保存在数据成员中,这样你就可以从onCreateView()返回它。

谢谢你的回答。鉴于WebView只是通过XML填充的片段中的几个视图之一,你会推荐采用什么方法? - RealCasually
1
@DerekJohnson:保留您膨胀的根视图。仅在其为“null”时才进行膨胀。仅在膨胀后调用loadUrl() - CommonsWare
1
当我将整个视图保存在实例变量中时,重新添加时会出现以下错误:java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 我知道我需要在onStop()中分离视图,但是getView()和getParent()没有提供removeAllViews()或removeView()方法。 - RealCasually
2
@DerekJohnson:将getParent()返回的ViewParent转换为ViewGroup,并调用适当的删除方法。 - CommonsWare
非常感谢你的帮助,Mark。我在FragmentTabHost中使用WebView时遇到了类似的问题,你的建议真是太有效了。 - danwilkie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接