当 ViewPager 中的 Fragment 从 BackStack 保留时 WebView 重新加载
Posted
技术标签:
【中文标题】当 ViewPager 中的 Fragment 从 BackStack 保留时 WebView 重新加载【英文标题】:WebView reloading when Fragment in ViewPager is retained form BackStack 【发布时间】:2013-04-22 18:41:56 【问题描述】:这是基本Fragment
的代码,其中包含WebView
。WebFragment.java
public class WebFragment extends Fragment
String TAG = "WebFragment";
private WebView webView;
private String currentUrl = "http://www.google.com";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
return inflater.inflate(R.layout.webview_layout, null);
@Override
public void onActivityCreated(Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
webView = (WebView) getView().findViewById(R.id.helloWebview);
initWebView();
webView.loadUrl(currentUrl);
@SuppressLint("SetjavascriptEnabled")
private void initWebView()
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(), "htmlOUT");
webView.setWebViewClient(new WebViewClient()
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
Log.e(TAG, "Loding...");
super.onPageStarted(view, url, favicon);
);
class JavaScriptInterface
public void showHTML(String html)
我还有两个基本片段(没有WebView
)。然后我使用FragmentAdapter
将所有这3个Fragments
放入ViewPager
(WebFragment
、Fragment1
和Fragment2
分别)。我在androidManifest.xml
中添加了android:configChanges="orientation|screenSize"
(所以WebView
不会在配置更改时重新生效)。
现在我的问题是,在运行应用程序时,我将ViewPager
的第一页(WebFragmet)更改为第二页(Fragment1
),然后我又回到了第一页。所以没问题WebFragment
就是这样。
现在我再次将ViewPager
更改为WebFragment
-->Fragment1
-->Fragment2
并通过反转上述操作的方向返回到第一页。但当时我看到WebFragment
中的WebView
正在重新加载。
还有一个问题,每当WebView
开始加载时,我都会看到 2 个类似的日志条目。
WebFragment Loading...
WebFragment Loading...
所以我的问题是:
1) 当WebFragment
从BackStack
保留时,如何防止WebView
重新加载?
2) 为什么在这里WebView
加载两次?
只要看到这个问题并帮助我(Prevent WebView reloads in FragmentPagerAdapter?)。
【问题讨论】:
【参考方案1】:在您定义 viewpager 的主要活动中
在 viewpager 声明之后,如下行:
ViewPager viewpager = (ViewPager) findViewById(R.id.pager);
添加这一行:
viewpager.setOffscreenPageLimit(2);
这将防止您的片段重新创建以滑动两个屏幕,因此当您在 viewpager 中从第 3 页返回到第 1 页时,您的 webview 将不会重新加载。
【讨论】:
@Chirag Shah 实际上我知道这一点(viewpager.setOffscreenPageLimit(2);
) 但如果我的ViewPager
中有5 个或更多Fragments
和WebView
如果我设置viewpager.setOffscreenPageLimit(5+);
,那将是一个不好的选择,对吗?你说什么?
你能回答我的第二个问题吗?
你能解释一下设置 offscreenlimit 有多糟糕吗?我认为防止你的片段被重新创建会很好。不是吗?我不确定你的第二个问题?可能是因为你正在调用 initWebView() 方法并且还写了这一行:webView.loadUrl(currentUrl);所以它被调用了两次。@VishalVijay
@Chirag Shah,我没有在initWebView()
中调用`webView.loadUrl(currentUrl);`,所以它不应该调用两次。
@Chirag Shah,使用viewpager.setOffscreenPageLimit(5+);
的问题是内存和性能。如果我将 5+ 设置为屏幕外限制。所有 5+ Fragments
都将在内存中,因此 Android
在低规格设备中可能存在性能问题。【参考方案2】:
这是一个典型的案例,通过简单的补丁修复覆盖android:configChanges
来解决问题。不幸的是,发生配置更改的原因有多种。所以简单地捕捉屏幕尺寸的变化会错过很多......正如你所发现的那样。
首先,彻底删除android:configChanges
。然后将以下内容添加到您的 WebView
片段中。
protected void onSaveInstanceState(Bundle outState)
webView.saveState(outState);
调整您的 WebView 片段的 onActivityCreated
方法以包含以下内容:
public void onActivityCreated(Bundle savedInstanceState)
webView = (WebView) getView().findViewById(R.id.helloWebview);
initWebView();
if (savedInstanceState != null)
webView.restoreState(savedInstanceState);
else
webView.loadUrl(currentUrl);
这应该会让你朝着正确的方向前进。注意,调用WebView
的saveState() 不会保存显示数据。例如,输入标签不会保留用户输入。您需要手动解析网页以保留该数据。根据您使用 WebView 的目的,这将是一个很大的痛苦。
【讨论】:
【参考方案3】:片段像这样使用。
A extends Fragment
static WebView w;
View v;
private Handler handler = new Handler()
@Override
public void handleMessage(Message message)
switch (message.what)
case 1:
webViewGoBack();
break;
private void webViewGoBack()
w.goBack();
// TODO Auto-generated method stub
;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
v = inflater.inflate(R.layout.webs, container, false);
w=(WebView)v.findViewById(R.id.webView1);
//w.loadUrl("");
w.setOnKeyListener(new OnKeyListener()
@Override
public boolean onKey(View v, int keyCode, KeyEvent event)
// TODO Auto-generated method stub
if((keyCode==KeyEvent.KEYCODE_BACK)&& w.canGoBack())
handler.sendEmptyMessage(1);
return true;
return false;
);
【讨论】:
以上是关于当 ViewPager 中的 Fragment 从 BackStack 保留时 WebView 重新加载的主要内容,如果未能解决你的问题,请参考以下文章
android - 将数据从 Activity 传递到 ViewPager 中的 Fragment
当 ViewPager 中的片段出现和消失时如何执行一些代码
如何从使用 Fragment 的 ViewPager2 获得用户点击?
如何从 MainActivity 中的 Fragment 访问适配器?我正在使用带有 viewpager 的标签,所以没有交易等方法