当 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 的代码,其中包含WebViewWebFragment.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放入ViewPagerWebFragmentFragment1Fragment2分别)。我在androidManifest.xml 中添加了android:configChanges="orientation|screenSize"(所以WebView 不会在配置更改时重新生效)。 现在我的问题是,在运行应用程序时,我将ViewPager 的第一页(WebFragmet)更改为第二页(Fragment1),然后我又回到了第一页。所以没问题WebFragment 就是这样。 现在我再次将ViewPager 更改为WebFragment-->Fragment1-->Fragment2 并通过反转上述操作的方向返回到第一页。但当时我看到WebFragment中的WebView正在重新加载。

还有一个问题,每当WebView 开始加载时,我都会看到 2 个类似的日志条目。

WebFragment Loading...
WebFragment Loading...

所以我的问题是: 1) 当WebFragmentBackStack 保留时,如何防止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 个或更多FragmentsWebView 如果我设置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 中的片段被重新创建

当 ViewPager 中的片段出现和消失时如何执行一些代码

如何从使用 Fragment 的 ViewPager2 获得用户点击?

如何从 MainActivity 中的 Fragment 访问适配器?我正在使用带有 viewpager 的标签,所以没有交易等方法

友盟页面统计 - 关于Viewpager中的Fragment的生命周期