【问题标题】:Android WebView: handling orientation changesAndroid WebView:处理方向变化
【发布时间】:2010-11-03 09:04:01
【问题描述】:

问题在于轮换后的性能。 WebView 必须重新加载页面,这可能有点乏味。

在不每次都从源重新加载页面的情况下,处理方向更改的最佳方法是什么?

【问题讨论】:

  • “从源重新加载”是指重新下载页面,还是只是重新渲染?
  • Blackhex 引用的解决方案解决了我的问题。
  • 我想知道我的应用到底有什么特别之处,以至于这些答案都不起作用...

标签: android webview orientation


【解决方案1】:

如果您不希望 WebView 在方向更改时重新加载,只需在 Activity 类中覆盖 onConfigurationChanged:

@Override
public void onConfigurationChanged(Configuration newConfig){        
    super.onConfigurationChanged(newConfig);
}

并在manifest中设置android:configChanges属性:

<activity android:name="..."
          android:label="@string/appName"
          android:configChanges="orientation|screenSize"

更多信息请见:
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

https://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges

【讨论】:

  • 我测试过但发现不起作用,像下面这样设置 configChanges 属性会起作用。 android:configChanges="keyboardHidden|orientation"
  • 实际上不鼓励这样做,正如之前多次提到的那样
  • Matthias:这不是真的 - 请参阅 Javadoc for WebView。
  • 关于此解决方案需要注意两点:1) 如果您有一个带有 WebView 的抽象 Activity,则将 configChanges 属性添加到子类 Activity 2) 如果您的应用程序依赖于多个项目,则configChanges 属性被添加到依赖树顶部(可能不是包含 Activity 类的项目)的清单中。
  • 这样的onConfigurationChanged方法覆盖没用。
【解决方案2】:

编辑:此方法不再像docs 中所述那样工作


原答案:

这可以通过覆盖您的活动中的onSaveInstanceState(Bundle outState) 并从网络视图调用saveState 来处理:

   protected void onSaveInstanceState(Bundle outState) {
      webView.saveState(outState);
   }

当然,在 webview 重新膨胀之后,在你的 onCreate 中恢复它:

public void onCreate(final Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.blah);
   if (savedInstanceState != null)
      ((WebView)findViewById(R.id.webview)).restoreState(savedInstanceState);
}

【讨论】:

  • 这不适用于方向更改 - 显示空白屏幕。调用了 saveState\restoreState 方法,但没有帮助。
  • 这里是 onCreate 代码 sn -p: setContentView(R.layout.webview); mWebView = (WebView) findViewById(R.id.webview); if (savedInstanceState == null) { mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebViewClient(new SimpleWebViewClient()); mWebView.loadUrl(Consts.URL_AUTHORIZATION_OAUTH); } else { mWebView.restoreState(savedInstanceState); }
  • 来自 saveState 的文档:请注意,此方法不再存储此 WebView 的显示数据。以前的行为可能会泄漏文件...
  • "请注意,此方法不再存储此 WebView 的显示数据" - developer.android.com/reference/android/webkit/WebView.html
  • 为了防止重新加载 WebView 表单,现在有没有人建议“此方法不再存储此 WebView 的显示数据”该怎么做?
【解决方案3】:

对此的最佳答案是遵循找到的 Android 文档 here 基本上这会阻止 Webview 重新加载:

<activity android:name=".MyActivity"
      android:configChanges="keyboardHidden|orientation|screenSize|layoutDirection|uiMode"
      android:label="@string/app_name">

编辑(2020 年 1 月 4 日):您不需要此可选代码,清单属性就是您所需要的,将可选代码留在这里以保持答案完整。

(可选),您可以通过覆盖活动中的onConfigurationChanged 来修复异常(如果有):

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

【讨论】:

  • 我很确定你不需要 onConfigurationChanged() 方法,只需要 Manifest 中的附加属性。我的猜测是 WebView 提供了对此的本机支持,这就是为什么这个答案现在是最好的答案(因为在最初提出问题时这不起作用)
  • 我同意@Booger,您不需要重写 onConfigurationChanged() 方法。您只需在 manifest.xml 文件中添加 android:configChanges="orientation|screenSize"。
  • @Booger 在回答中还说,该代码是可选的,不是强制性的。
【解决方案4】:

我尝试使用 onRetainNonConfigurationInstance(返回 WebView),然后在 onCreate 期间使用 getLastNonConfigurationInstance 将其取回> 并重新分配它。

似乎还没有工作。我不禁认为我真的很亲近!到目前为止,我只是得到一个空白/白色背景的 WebView。在这里发帖是希望有人可以帮助将其推过终点线。

也许我不应该传递 WebView。可能是 WebView 中的一个对象?

我尝试的另一种方法——不是我最喜欢的——是在活动中设置它:

 android:configChanges="keyboardHidden|orientation"

...然后在这里几乎什么都不做:

@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  // We do nothing here. We're only handling this to keep orientation
  // or keyboard hiding from causing the WebView activity to restart.
}

这行得通,但它可能不被视为best practice

同时,我还有一个 ImageView 我想根据旋转自动更新。事实证明这很容易。在我的res 文件夹下,我有drawable-landdrawable-port 来保存横向/纵向变化,然后我使用R.drawable.myimagename 作为ImageView 的源,Android“做正确的事” - 耶!

...除非您注意配置更改,否则它不会。 :(

所以我很矛盾。使用 onRetainNonConfigurationInstanceImageView 旋转工作,但 WebView 持久性不...或使用 onConfigurationChangedWebView 保持稳定,但 ImageView 不会更新。怎么办?

最后一点:就我而言,强制定向不是可接受的折衷方案。我们真的很想优雅地支持轮换。有点像 Android 浏览器应用程序的功能! ;)

【讨论】:

  • 您不应从 onRetainNonConfigurationInstance 返回任何视图。视图附加到活动上下文中,因此如果您保存视图,则每次发生方向更改时都会携带所有行李。该视图被“泄露”。 (请参阅此处的最后一段:developer.android.com/resources/articles/…) onRetainNonConfigurationInstance 的最佳做法是保存视图需要的数据,而不是视图本身。
【解决方案5】:

处理方向变化和防止 WebView 在旋转时重新加载的最佳方法。

@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}

考虑到这一点,为了防止每次更改方向时都调用 onCreate(),您必须添加 android:configChanges="orientation|screenSize" to the AndroidManifest.

或者只是..

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"`

【讨论】:

    【解决方案6】:

    感谢这有点晚了,但这是我在开发解决方案时使用的答案:

    AndroidManifest.xml

        <activity
            android:name=".WebClient"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize" <--- "screenSize" important
            android:label="@string/title_activity_web_client" >
        </activity>
    

    WebClient.java

    public class WebClient extends Activity {
    
        protected FrameLayout webViewPlaceholder;
        protected WebView webView;
    
        private String WEBCLIENT_URL;
        private String WEBCLIENT_TITLE;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_web_client);
            initUI();
        }
    
        @SuppressLint("SetJavaScriptEnabled")
        protected void initUI(){
            // Retrieve UI elements
            webViewPlaceholder = ((FrameLayout)findViewById(R.id.webViewPlaceholder));
    
            // Initialize the WebView if necessary
            if (webView == null)
            {
                // Create the webview
                webView = new WebView(this);
                webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
                webView.getSettings().setSupportZoom(true);
                webView.getSettings().setBuiltInZoomControls(true);
                webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
                webView.setScrollbarFadingEnabled(true);
                webView.getSettings().setJavaScriptEnabled(true);
                webView.getSettings().setPluginState(android.webkit.WebSettings.PluginState.ON);
                webView.getSettings().setLoadsImagesAutomatically(true);
    
                // Load the URLs inside the WebView, not in the external web browser
                webView.setWebViewClient(new SetWebClient());
                webView.setWebChromeClient(new WebChromeClient());
    
                // Load a page
                webView.loadUrl(WEBCLIENT_URL);
            }
    
            // Attach the WebView to its placeholder
            webViewPlaceholder.addView(webView);
        }
    
        private class SetWebClient extends WebViewClient {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.web_client, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }else if(id == android.R.id.home){
                finish();
                return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    
        @Override
        public void onBackPressed() {
            if (webView.canGoBack()) {
                webView.goBack();
                return;
            }
    
            // Otherwise defer to system default behavior.
            super.onBackPressed();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig){
            if (webView != null){
                // Remove the WebView from the old placeholder
                webViewPlaceholder.removeView(webView);
            }
    
            super.onConfigurationChanged(newConfig);
    
            // Load the layout resource for the new configuration
            setContentView(R.layout.activity_web_client);
    
            // Reinitialize the UI
            initUI();
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState){
            super.onSaveInstanceState(outState);
    
            // Save the state of the WebView
            webView.saveState(outState);
        }
    
        @Override
        protected void onRestoreInstanceState(Bundle savedInstanceState){
            super.onRestoreInstanceState(savedInstanceState);
    
            // Restore the state of the WebView
            webView.restoreState(savedInstanceState);
        }
    
    }
    

    【讨论】:

      【解决方案7】:

      一种折衷方案是避免轮换。 添加此项以修复仅纵向方向的活动。

      android:screenOrientation="portrait"
      

      【讨论】:

      • 这实际上在很多情况下都有效,并且是我决定实施的解决方案:-)
      • 呵呵,这是需求变更
      【解决方案8】:

      只需在您的清单文件中编写以下代码行 - 仅此而已。它确实有效:

      <activity android:name=".YourActivity"
        android:configChanges="orientation|screenSize"
        android:label="@string/application_name">
      

      【讨论】:

        【解决方案9】:

        您可以尝试在 Activity 上使用 onSaveInstanceState()onRestoreInstanceState() 在 WebView 实例上调用 saveState(...)restoreState(...)

        【讨论】:

          【解决方案10】:

          现在是 2015 年,许多人正在寻找一种仍然适用于 Jellybean、KK 和 Lollipop 手机的解决方案。 在很多挣扎之后,我找到了一种在你改变方向后保持 webview 完好无损的方法。 我的策略基本上是将 webview 存储在另一个类的单独静态变量中。然后,如果发生旋转,我将 webview 从 Activity 中分离出来,等待方向完成,然后将 webview 重新附加到 Activity。 例如...首先将其放在您的清单上(keyboardHidden 和键盘是可选的):

          <application
                  android:label="@string/app_name"
                  android:theme="@style/AppTheme"
                  android:name="com.myapp.abc.app">
          
              <activity
                      android:name=".myRotatingActivity"
                      android:configChanges="keyboard|keyboardHidden|orientation">
              </activity>
          

          在单独的应用程序类中,输入:

               public class app extends Application {
                      public static WebView webview;
                      public static FrameLayout webviewPlaceholder;//will hold the webview
          
                   @Override
                         public void onCreate() {
                             super.onCreate();
              //dont forget to put this on the manifest in order for this onCreate method to fire when the app starts: android:name="com.myapp.abc.app"
                             setFirstLaunch("true");
                     }
          
                 public static String isFirstLaunch(Context appContext, String s) {
                     try {
                    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
                    return prefs.getString("booting", "false");
                    }catch (Exception e) {
                       return "false";
                    }
                  }
          
              public static void setFirstLaunch(Context aContext,String s) {
                 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(aContext);
                      SharedPreferences.Editor editor = prefs.edit();
                      editor.putString("booting", s);
                      editor.commit();
                     }
                  }
          

          在 ACTIVITY 中放置:

          @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_main);
                  if(app.isFirstLaunch.equals("true"))) {
                      app.setFirstLaunch("false");
                      app.webview = new WebView(thisActivity);
                      initWebUI("www.mypage.url");
                  }
          }
          @Override
              public  void onRestoreInstanceState(Bundle savedInstanceState) {
                  restoreWebview();
              }
          
          public void restoreWebview(){
                  app.webviewPlaceholder = (FrameLayout)thisActivity.findViewById(R.id.webviewplaceholder);
                  if(app.webviewPlaceholder.getParent()!=null&&((ViewGroup)app.webview.getParent())!=null) {
                      ((ViewGroup) app.webview.getParent()).removeView(app.webview);
                  }
                  RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
                  app.webview.setLayoutParams(params);
                  app.webviewPlaceholder.addView(app.webview);
                  app.needToRestoreWebview=false;
              }
          
          protected static void initWebUI(String url){
                  if(app.webviewPlaceholder==null);
                    app.webviewPlaceholder = (FrameLayout)thisActivity.findViewById(R.id.webviewplaceholder);
                  app.webview.getSettings().setJavaScriptEnabled(true);       app.webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
                  app.webview.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
                  app.webview.getSettings().setSupportZoom(false);
                  app.webview.getSettings().setBuiltInZoomControls(true);
                  app.webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
                  app.webview.setScrollbarFadingEnabled(true);
                  app.webview.getSettings().setLoadsImagesAutomatically(true);
                  app.webview.loadUrl(url);
                  app.webview.setWebViewClient(new WebViewClient());
                  if((app.webview.getParent()!=null)){//&&(app.getBooting(thisActivity).equals("true"))) {
                      ((ViewGroup) app.webview.getParent()).removeView(app.webview);
                  }
                  app.webviewPlaceholder.addView(app.webview);
              }
          

          最后是简单的 XML:

          <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context=".myRotatingActivity">
              <FrameLayout
                  android:id="@+id/webviewplaceholder"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  />
          </RelativeLayout>
          

          在我的解决方案中有几处可以改进的地方,但我已经花了很多时间,例如:一种更短的方法来验证 Activity 是否是第一次启动,而不是使用 SharedPreferences 存储。 这种方法可以使您的 webview 保持完整(afaik),它的文本框、标签、UI、javascript 变量和导航状态不会被 url 反映。

          【讨论】:

          • 既然您手动处理配置更改,既然 WebView 从一开始就不会被破坏,为什么还要费心分离和重新附加 WebView?
          • @Fred 因为我想保持 Webview 的确切状态及其内容完好无损,包括 cookie,以及在 Webview 加载的网页中使用 HTML5 或 JS 实现的按钮和复选框的状态。我做的唯一调整就是调整大小。
          • Fred 意味着您不需要通过静态类分离/重新附加 Web 视图,因为您在清单中声明了 configChanges。这样,您的视图和活动在任何情况下都不会在轮换期间被破坏。
          【解决方案11】:

          您唯一应该做的就是将此代码添加到清单文件中:

          <activity android:name=".YourActivity"
                android:configChanges="orientation|screenSize"
                android:label="@string/application_name">
          

          【讨论】:

            【解决方案12】:

            更新:当前的策略是将 WebView 实例移动到 Application 类,而不是像 Josh 那样在分离时保留片段并在恢复时重新附加。 为了防止应用程序关闭,您应该使用前台服务,如果您想在用户在应用程序之间切换时保留状态。

            如果您正在使用片段,则可以使用 WebView 的保留实例。 Web 视图将保留为该类的实例成员。但是,您应该在 OnCreateView 中附加 Web 视图并在 OnDestroyView 之前分离,以防止它被父容器破坏。

            class MyFragment extends Fragment{  
            
                public MyFragment(){  setRetainInstance(true); }
            
                private WebView webView;
            
                @Override
                public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                   View v = ....
                   LinearLayout ll = (LinearLayout)v.findViewById(...);
                   if (webView == null) {
                        webView = new WebView(getActivity().getApplicationContext()); 
                   }
                   ll.removeAllViews();
                   ll.addView(webView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            
                   return v;
                }
            
                @Override
                public void onDestroyView() {
                    if (getRetainInstance() && webView.getParent() instanceof ViewGroup) {
                       ((ViewGroup) webView.getParent()).removeView(webView);
                    }
                    super.onDestroyView();
                } 
            }
            

            附:学分转到kcoppock answer

            对于 'SaveState()' 它不再根据official documentation 工作:

            请注意,此方法不再存储显示数据 这个 Web 视图。如果之前的行为可能会泄漏文件 restoreState(Bundle) 从未被调用过。

            【讨论】:

            • 请注意,虽然setRetainInstance 确实保留了 Fragment,但视图(以及 WebView)仍然会被破坏。
            • @Fred 您能否提供该声明的来源?我已经在一个小应用程序中对此进行了测试,该应用程序有一个带有 setRetainInstance(true) 的片段,它显示一个 youtube 页面,如果我改变方向,由于视频没有中断,视图似乎会被保留。 webview 似乎没有被破坏。
            • @Rai 这只是一个误读,从那时起我已经编辑了一些答案(它仍然需要一些措辞修复)。如果您对当前的事态感兴趣 - 此方法有效。然而问题是android在内存不足时会杀死应用程序。我有一个重要的输入表单,用户必须在另一个应用程序中阅读消息,所以我必须使用带有通知的前台服务来防止进程被杀死。然而,android 仍然会破坏活动,因此会破坏保留的框架。但是 Application 类的实例被保留了 - 所以我现在将 WebView 移动到 Application。
            • 我还使用 MutableContextWrapper 作为 WebView 的基础,我将上下文切换到附加和分离的活动。 Chromium 内置缩放控件的另一个大问题是保存对旧活动的引用,因此没有将 WebView 附加到应用程序而不是活动的放大解决方案。 TL;DR; 如果您的表单不是那么重要,并且您可能会接受这样的事实,即在应用程序切换后您的进程可能会被终止并且 webview 无法恢复,请使用保留框架解决方案。附言我还认为,Google 员工的所有小工具和小工具都与现实生活中的问题相去甚远。
            【解决方案13】:
            @Override
            protected void onSaveInstanceState(Bundle outState) {
                super.onSaveInstanceState(outState);    
            }
            
            @Override
            protected void onRestoreInstanceState(Bundle state) {
                super.onRestoreInstanceState(state);    
            }
            

            这些方法可以在任何活动上被覆盖,它基本上允许您在每次创建/销毁活动时保存和恢复值,当屏幕方向更改时,活动被销毁并在后台重新创建,因此您可以使用这些方法在更改期间临时存储/恢复状态。

            您应该深入了解以下两种方法,看看它是否适合您的解决方案。

            http://developer.android.com/reference/android/app/Activity.html

            【讨论】:

              【解决方案14】:

              我发现在不泄露之前的 Activity 引用且不设置 configChanges.. 的情况下执行此操作的最佳解决方案是使用 MutableContextWrapper

              我在这里实现了这个:https://github.com/slightfoot/android-web-wrapper/blob/48cb3c48c457d889fc16b4e3eba1c9e925f42cfb/WebWrapper/src/com/example/webwrapper/BrowserActivity.java

              【讨论】:

              • 这项工作是否可靠且无副作用?我没有找到关于这个方法的太多信息。
              【解决方案15】:

              这是唯一对我有用的东西(我什至在onCreateView 中使用了保存实例状态,但它并不可靠)。

              public class WebViewFragment extends Fragment
              {
                  private enum WebViewStateHolder
                  {
                      INSTANCE;
              
                      private Bundle bundle;
              
                      public void saveWebViewState(WebView webView)
                      {
                          bundle = new Bundle();
                          webView.saveState(bundle);
                      }
              
                      public Bundle getBundle()
                      {
                          return bundle;
                      }
                  }
              
                  @Override
                  public void onPause()
                  {
                      WebViewStateHolder.INSTANCE.saveWebViewState(myWebView);
                      super.onPause();
                  }
              
                  @Override
                  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                      Bundle savedInstanceState)
                  {
                      View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
                      ButterKnife.inject(this, rootView);
                      if(WebViewStateHolder.INSTANCE.getBundle() == null)
                      {
                          StringBuilder stringBuilder = new StringBuilder();
                          BufferedReader br = null;
                          try
                          {
                              br = new BufferedReader(new InputStreamReader(getActivity().getAssets().open("start.html")));
              
                              String line = null;
                              while((line = br.readLine()) != null)
                              {
                                  stringBuilder.append(line);
                              }
                          }
                          catch(IOException e)
                          {
                              Log.d(getClass().getName(), "Failed reading HTML.", e);
                          }
                          finally
                          {
                              if(br != null)
                              {
                                  try
                                  {
                                      br.close();
                                  }
                                  catch(IOException e)
                                  {
                                      Log.d(getClass().getName(), "Kappa", e);
                                  }
                              }
                          }
                          myWebView
                              .loadDataWithBaseURL("file:///android_asset/", stringBuilder.toString(), "text/html", "utf-8", null);
                      }
                      else
                      {
                          myWebView.restoreState(WebViewStateHolder.INSTANCE.getBundle());
                      }
                      return rootView;
                  }
              }
              

              我为 WebView 的状态制作了一个单例持有者。只要应用程序的进程存在,状态就会被保留。

              编辑:loadDataWithBaseURL 不是必需的,它与 just 一样有效

                  //in onCreate() for Activity, or in onCreateView() for Fragment
              
                  if(WebViewStateHolder.INSTANCE.getBundle() == null) {
                      webView.loadUrl("file:///android_asset/html/merged.html");
                  } else {
                      webView.restoreState(WebViewStateHolder.INSTANCE.getBundle());
                  }
              

              虽然我读到这不一定适用于 cookie。

              【讨论】:

              • 使用单例是有问题的,因为它假定您只有一个需要使用的实例。
              • @androiddeveloper 啊。好吧,如果您的情况不是这样,那么这确实是一个问题。我只有一个 WebView 实例,所以我什至没有想到这个问题。
              【解决方案16】:

              试试这个

              import android.os.Bundle;
              import android.support.v7.app.AppCompatActivity;
              import android.view.View;
              import android.webkit.WebView;
              import android.webkit.WebViewClient;
              
              public class MainActivity extends AppCompatActivity {
              
                  private WebView wv;
              
                  @Override
                  protected void onCreate(Bundle savedInstanceState) {
                      super.onCreate(savedInstanceState);
                      setContentView(R.layout.activity_main);
              
                      wv = (WebView) findViewById(R.id.webView);
                      String url = "https://www.google.ps/";
              
                      if (savedInstanceState != null)
                          wv.restoreState(savedInstanceState);
                      else {
                          wv.setWebViewClient(new MyBrowser());
                          wv.getSettings().setLoadsImagesAutomatically(true);
                          wv.getSettings().setJavaScriptEnabled(true);
                          wv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
                          wv.loadUrl(url);
                      }
                  }
              
                  @Override
                  protected void onSaveInstanceState(Bundle outState) {
                      super.onSaveInstanceState(outState);
                      wv.saveState(outState);
                  }
              
                  @Override
                  public void onBackPressed() {
                      if (wv.canGoBack())
                          wv.goBack();
                      else
                          super.onBackPressed();
                  }
              
                  private class MyBrowser extends WebViewClient {
                      @Override
                      public boolean shouldOverrideUrlLoading(WebView view, String url) {
                          view.loadUrl(url);
                          return true;
                      }
                  }
              
              }
              

              【讨论】:

                【解决方案17】:

                此页面解决了我的问题,但我必须对初始页面稍作改动:

                    protected void onSaveInstanceState(Bundle outState) {
                       webView.saveState(outState);
                       }
                

                这部分对我来说有点小问题。在第二个方向更改应用程序以空指针终止

                使用它对我有用:

                    @Override
                protected void onSaveInstanceState(Bundle outState ){
                    ((WebView) findViewById(R.id.webview)).saveState(outState);
                }
                

                【讨论】:

                • 似乎完全一样。为什么第二个可以工作,而前一个不行?
                【解决方案18】:

                你应该试试这个:

                1. 创建一个服务,在该服务内部,创建您的 WebView。
                2. 从您的活动启动服务并绑定到它。
                3. onServiceConnected方法中,获取WebView并调用setContentView方法来渲染你的WebView。

                我对其进行了测试,它可以工作,但不适用于 XWalkView 或 GeckoView 等其他 WebView。

                【讨论】:

                • 嗨!你能再解释一下吗?谢谢
                • 好吧,从你的 Activity 中获取你的 webview 实例,并尝试将它的引用放到后台运行的服务中。下次打开该活动时,请先尝试获取保存的 webview 并进行渲染。
                【解决方案19】:
                @Override
                    protected void onSaveInstanceState(Bundle outState )
                    {
                        super.onSaveInstanceState(outState);
                        webView.saveState(outState);
                    }
                
                    @Override
                    protected void onRestoreInstanceState(Bundle savedInstanceState)
                    {
                        super.onRestoreInstanceState(savedInstanceState);
                        webView.restoreState(savedInstanceState);
                    }
                

                【讨论】:

                • 你能在你的答案中添加一些解释吗?
                【解决方案20】:

                我喜欢这个解决方案http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/

                据此,我们重用了相同的 WebView 实例。它允许在配置更改时保存导航历史记录和滚动位置。

                【讨论】:

                • 上面的链接指向一个页面,如果不安装一些“安全插件”就无法查看;避免。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-01-19
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多