2016-04-22 89 views
2

我知道这已经被问过太多次了,并且SO里面充满了类似的问题。我经历了其中的大部分,我一直在研究这个问题几天,我还没有找到最终的解决方案。防止WebView片段在屏幕旋转上重新加载页面

我可以很容易地避免所有这些麻烦添加configChanges="orientation|screenSize"到包含WebView的活动;我已经测试过了,它按预期工作(WebView没有重新加载)。 但我真的很想避免这个解决方案。

这里是我当前的WebView实现:

public class BrowserFragment extends Fragment { 

    private WebView mWebView; 

    public BrowserFragment() { 
     // Required empty public constructor 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setRetainInstance(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     if (mWebView == null) { 
      mWebView = new WebView(getActivity()); 
     } 

     return mWebView; 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 

     mWebView.setWebViewClient(new WebViewClient() { 

      @Override 
      public boolean shouldOverrideUrlLoading(WebView view, String url) { 
       return super.shouldOverrideUrlLoading(view, url); 
      } 

     }); 

     mWebView.getSettings().setAllowFileAccess(true); 
     mWebView.getSettings().setBuiltInZoomControls(false); 
     mWebView.getSettings().setDomStorageEnabled(true); 
     mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 
     mWebView.getSettings().setJavaScriptEnabled(true); 
     mWebView.getSettings().setSupportZoom(false); 

     if (savedInstanceState == null) { 
      mWebView.loadUrl("http://developer.android.com/"); 
     } else { 
      mWebView.restoreState(savedInstanceState); 
     } 
    } 

    @Override 
    public void onResume() { 
     mWebView.onResume(); 

     super.onResume(); 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 

     mWebView.onPause(); 
    } 

    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 

     mWebView.saveState(outState); 
    } 

    @Override 
    public void onDestroyView() { 
     if (getRetainInstance() && mWebView.getParent() instanceof ViewGroup) { 
      ((ViewGroup) mWebView.getParent()).removeView(mWebView); 
     } 

     super.onDestroyView(); 
    } 

} 

至于MainActivity,有什么也没有,除了内容视图设置为以下布局文件:

<?xml version="1.0" encoding="utf-8"?> 
<merge xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

    <fragment 
     android:id="@+id/fragment_browser" 
     android:name="com.example.app.BrowserFragment" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" /> 

</merge> 

注意上面,我是保留片段实例,并且我还保存了WebView的状态,以便我可以延迟恢复相同的状态。这是关于restoreState方法的文档必须说明的内容:

从给定的Bundle中还原此WebView的状态。此方法 旨在用于onRestoreInstanceState(Bundle),并应调用 来恢复此WebView的状态。如果在调用 后调用此WebView有机会构建状态(加载页面,创建 后退/前进列表等),则可能会产生不良副作用。 请 请注意,此方法不再为此 WebView恢复显示数据。

意思是,显示数据将不会被恢复,但像滚动位置的东西(我也测试过这个,它很好地工作)。这就是为什么我要创建一个WebView的新实例,只有在onCreateView期间它是null并在onDestroyView期间将其从父视图中删除。这是从这个答案:https://stackoverflow.com/a/32801278/40480

这种机制将使旋转过程更平稳(没有它,一个完整的空白页面显示),但不会阻止WebView仍然重新加载页面。

任何想法我怎么可能可以解决这个问题?

回答

1

我有一个类似的问题。这是一个有点晚了,但我的解决办法是比你相似,但再次添加web视图中onCreateView布局:

  • 创造新的WebView如果实例为null(第一次),并把它添加到布局(在我的情况父一个FrameLayout,在位置0)。
  • 如果已经创建(活动重新)只需添加到帧和无效(重要重绘上旋转的WebView)

    mFrame = (FrameLayout) mView.findViewById(R.id.dq_fragment_browser_common_frame); 
    
    if (mWebView == null){ 
        mWebView = new CommonWebView(getContext()); 
        mFrame.addView(mWebView,0); 
    } else { 
        mFrame.addView(mWebView,0); 
        mWebView.invalidate(); 
    } 
    

在你的情况下,我从框架OnDestroyView删除的WebView()是能够在onCreateView再次添加它:

@Override 
public void onDestroyView() { 
    mFrame.removeView(mWebView); 
    super.onDestroyView(); 
} 

注:我不保存和存储web视图状态,因为它重新加载页面(至少在我的情况)。此外,滚动位置在纵向/横向上通常不匹配,但Chrome浏览器中的问题与我查看的一样。

问候。