Android WebView: обработка изменений ориентации - PullRequest
138 голосов
/ 16 июня 2009

Проблема в производительности после ротации. WebView должен перезагрузить страницу, что может быть немного утомительно.

Какой лучший способ обработки изменения ориентации без перезагрузки страницы из источника каждый раз?

Ответы [ 20 ]

1 голос
/ 19 ноября 2014

Это единственное, что сработало для меня (я даже использовал состояние экземпляра сохранения в 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;
    }
}

Я сделал держатель Singleton для состояния WebView. Состояние сохраняется до тех пор, пока существует процесс приложения.

РЕДАКТИРОВАТЬ: loadDataWithBaseURL не было необходимости, оно работало так же хорошо с просто

    //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());
    }

Хотя я читаю, это не обязательно хорошо работает с куки.

1 голос
/ 06 мая 2014

Лучшее решение, которое я нашел, чтобы сделать это без утечки предыдущей ссылки Activity и без установки configChanges .., это использовать MutableContextWrapper .

Я реализовал это здесь: https://github.com/slightfoot/android-web-wrapper/blob/48cb3c48c457d889fc16b4e3eba1c9e925f42cfb/WebWrapper/src/com/example/webwrapper/BrowserActivity.java

1 голос
/ 12 июля 2009
@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

1 голос
/ 16 января 2018

Просто напишите следующие строки кода в вашем файле манифеста - больше ничего. Это действительно работает:

<activity android:name=".YourActivity"
  android:configChanges="orientation|screenSize"
  android:label="@string/application_name">
1 голос
/ 08 января 2016

Единственное, что вам нужно сделать, это добавить этот код в файл манифеста:

<activity android:name=".YourActivity"
      android:configChanges="orientation|screenSize"
      android:label="@string/application_name">
0 голосов
/ 09 января 2019

попробуйте

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;
        }
    }

}
0 голосов
/ 17 ноября 2017
@Override
    protected void onSaveInstanceState(Bundle outState )
    {
        super.onSaveInstanceState(outState);
        webView.saveState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState)
    {
        super.onRestoreInstanceState(savedInstanceState);
        webView.restoreState(savedInstanceState);
    }
0 голосов
/ 12 октября 2011

Эта страница решает мою проблему, но я должен внести небольшое изменение в исходную:

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

Эта часть имеет небольшую проблему для меня это. При втором изменении ориентации приложение завершается нулевым указателем

с помощью этого он работал для меня:

    @Override
protected void onSaveInstanceState(Bundle outState ){
    ((WebView) findViewById(R.id.webview)).saveState(outState);
}
0 голосов
/ 31 января 2016

Вы должны попробовать это:

  1. Создайте службу, внутри этой службы создайте свой WebView.
  2. Запустите сервис из своей активности и привяжите к нему.
  3. В методе onServiceConnected получите WebView и вызовите метод setContentView для визуализации вашего WebView.

Я протестировал его, и он работает, но не с другими WebViews, такими как XWalkView или GeckoView.

0 голосов
/ 19 июля 2014

Мне нравится это решение http://www.devahead.com/blog/2012/01/preserving-the-state-of-an-android-webview-on-screen-orientation-change/

В соответствии с этим мы повторно используем тот же экземпляр WebView. Позволяет сохранить историю навигации и положение прокрутки при изменении конфигурации.

...