【问题标题】:Prevent WebView fragment from reloading page on screen rotation防止 WebView 片段在屏幕旋转时重新加载页面
【发布时间】:2016-04-22 18:14:47
【问题描述】:

我知道这个问题已经被问过太多次了,而且这里充满了类似的问题。我经历了其中的大部分,我已经研究了几天这个问题,但我还没有找到最终的解决方案。

我可以很容易地避免将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 的新实例,前提是它在 onCreateView 期间为 null 并在 onDestroyView 期间将其从父视图中删除。这取自这个答案:https://stackoverflow.com/a/32801278/40480

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

有什么办法可以解决这个问题吗?

【问题讨论】:

  • 你解决过这个问题吗?我正在处理类似的问题,就像你说的那样,我在这里发现的其他案例无法帮助我。测试您的代码,我注意到问题不仅与屏幕旋转有关,因为如果我们切换选项卡也会重新加载。我认为这与onCreate() 有关,但我还没有找到正确的方法。好吧,欢迎任何关于这个问题的意见,muito obrigado

标签: android android-fragments webview page-refresh


【解决方案1】:

我遇到了类似的问题。有点晚了,但我的解决方法与您的类似,但将 webview 再次添加到 onCreateView 的布局中:

  • 如果实例为 null(第一次),则创建新的 WebView 并将其添加到布局中(在我的情况下,父级是 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();
}

注意:我不会在重新加载页面时保存和存储 webview 状态(至少在我的情况下)。此外,据我检查,滚动位置在纵向/横向中通常不匹配,但在 Chrome 中存在同样的问题。

问候。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 1970-01-01
    • 2014-04-16
    • 2015-06-17
    相关资源
    最近更新 更多