Android Web Görünümü: yön değişikliklerini işleme


147

Sorun rotasyonu izleyen performanstır. WebView, sayfayı yeniden yüklemelidir, bu biraz sıkıcı olabilir.

Her seferinde sayfayı kaynaktan yeniden yüklemeden bir yön değişikliğini işlemenin en iyi yolu nedir?


3
"Kaynaktan yeniden yükleme" derken, sayfayı tekrar indirdiğini mi yoksa yalnızca yeniden oluşturduğunu mu kastediyorsunuz?
Jeremy Logan

Blackhex'in referans verdiği çözüm sorunumu çözdü.
Italo Borssatto

6
Merak ediyorum, uygulamam hakkında bu cevapların hiçbiri işe yaramayacak kadar özel ...
RobinJ

Yanıtlar:


91

Web Görünümü'nün yön değişikliklerinde yeniden yüklenmesini istemiyorsanız, Activity sınıfınızda onConfigurationChanged öğesini geçersiz kılmanız yeterlidir:

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

Ve manifest'te android: configChanges özniteliğini ayarlayın:

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

daha fazla bilgi için bkz:
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

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


4
Test ettim ancak çalışmadığını buldum, aşağıdaki gibi ayarlanan configChanges özniteliği çalışacak. android: configChanges = "keyboardHidden | orientation"
virsir

18
bunu yapmak aslında cesaret kırıcıdır, daha önce birçok kez bahsedildiği gibi
Matthias

3
Matthias: Bu gerçekten doğru değil - WebView için Javadoc'a bakın.
krtek

Bu çözümle ilgili dikkat edilmesi gereken iki nokta: 1) Web Görünümü ile soyut bir Aktiviteniz varsa, configChangesözellik alt sınıfa eklenir Aktivite 2) Uygulamanız birden çok projeye bağlıysa, configChangesöznitelik şuradaki birinin bildirimine eklenir. bağımlılık ağacının tepesi (Activity sınıfını içeren proje olmayabilir).
Amanda S

4
Böyle bir onConfigurationChangedyöntem geçersiz kılma işe yaramaz.
Miha_x64

69

Düzenleme: Bu yöntem artık belgelerde belirtildiği gibi çalışmıyor


Orijinal cevap:

Bu, onSaveInstanceState(Bundle outState)etkinliğinizin üzerine yazarak saveStateve web görünümünden arayarak çözülebilir :

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

Elbette web görünümü yeniden şişirildikten sonra bunu onCreate içinde kurtarın:

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

26
Bu, yön değişikliğinde çalışmaz - boş ekran gösterilir. saveState \ restoreState yöntemleri çağrılır, ancak yardımcı olmaz.
Oleksii Malovanyi

1
İşte onCreate kod parçacığı: setContentView (R.layout.webview); mWebView = (WebView) findViewById (R.id.webview); eğer (SavedInstanceState == null) {mWebView.getSettings (). setJavaScriptEnabled (true); mWebView.setWebViewClient (yeni SimpleWebViewClient ()); mWebView.loadUrl (Consts.URL_AUTHORIZATION_OAUTH); } else {mWebView.restoreState (SavedInstanceState); }
Oleksii Malovanyi

12
SaveState belgelerinden: Lütfen bu yöntemin artık bu Web Görünümü için görüntü verilerini
brillenheini

5
"Lütfen bu yöntemin artık bu Web Görünümü için ekran verilerini depolamadığını unutmayın" - developer.android.com/reference/android/webkit/WebView.html
Steven Mark Ford

Bir Web Görünümü formunun yeniden yüklenmesini önlemek için "bu yöntem artık bu Web Görünümü için görüntü verilerini saklamadığına" şimdi ne yapılması gerektiğine dair herhangi bir önerisi var mı?
Lucas P.

24

Buna en iyi cevap, burada bulunan Android belgelerini takip etmektir Temel olarak bu, Webview'un yeniden yüklenmesini engelleyecektir:

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

İsteğe bağlı olarak , onConfigurationChangedetkinliği geçersiz kılarak anormallikleri (varsa) düzeltebilirsiniz :

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

6
OnConfigurationChanged () yöntemine ihtiyacınız yok, eminim, sadece Manifest'teki ek öznitelik. Tahminimce bunun için yerel destek WebView tarafından sağlandı ve bu yüzden bu yanıt şu anda en iyisi (çünkü soru ilk sorulduğunda bu işe yaramadı)
Booger

1
@Booger'ı onaylıyorum, onConfigurationChanged () yöntemini geçersiz kılmanıza gerek yok. İhtiyacınız olan tek şey, manifest.xml dosyasına android: configChanges = "orientation | screenSize" eklemektir.
ozanurkan

5

Ben kullanarak denedim onRetainNonConfigurationInstance (dönen WebView'ı sonra tekrar onu almak,) getLastNonConfigurationInstance sırasında onCreate ve onu yeniden atama.

Henüz işe yaramıyor gibi görünüyor. Yardım edemem ama gerçekten yakın olduğumu düşünüyorum! Şimdiye kadar, boş / beyaz arka planlı bir Web Görünümü görüyorum bunun yerine . Birinin bunu bitiş çizgisini geçmeye yardımcı olabileceği umuduyla buraya yazıyorum.

Belki Web Görünümü'nü geçmemeliyim . Belki WebView içinden bir nesne ?

En sevdiğim değil denediğim diğer yöntem, bunu etkinlikte ayarlamak:

 android:configChanges="keyboardHidden|orientation"

... ve sonra burada hemen hemen hiçbir şey yapmayın:

@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.
}

BU işe yarıyor, ancak bir en iyi uygulama olarak kabul edilmeyebilir .

Bu arada, rotasyona bağlı olarak otomatik olarak güncellemek istediğim tek bir ImageView de var . Bu çok kolay çıktı. resKlasörümün altında , manzara / portre varyasyonlarına sahibim drawable-landve drawable-portbunları tutmak R.drawable.myimagenameiçin, ImageView kaynağı için kullanıyorum ve Android "doğru olanı yapıyor" - yaşasın!

... yapılandırma değişikliklerini izlemeniz dışında, o zaman izlemez. :(

Bu yüzden anlaşmazlık içindeyim. OnRetainNonConfigurationInstance kullanın ve ImageView rotasyonu çalışır, ancak WebView kalıcılığı kullanılmaz ... veya onConfigurationChanged ve WebView sabit kalır, ancak ImageView güncellenmez. Ne yapalım?

Son bir not: Benim durumumda, yönelimi zorlamak kabul edilebilir bir uzlaşma değil. Gerçekten rotasyonu incelikle desteklemek istiyoruz. Android Tarayıcı uygulamasının yaptığı gibi! ;)


8
OnRetainNonConfigurationInstance'tan herhangi bir Görünüm döndürmemelisiniz. Görünümler, Aktivite Bağlamına eklenir, böylece görünümü kaydederseniz, her yön değişikliği olduğunda tüm bu bagajı taşırsınız. Görünüm "sızdırıldı". (Buradaki son paragrafa bakın: developer.android.com/resources/articles/… ) onRetainNonConfigurationInstance için en iyi uygulama, görünümün kendisini değil, görünümün ihtiyaç duyduğu verileri kaydetmektir.
Declan Shanaghy

4

Yön değişikliklerini işlemenin ve Döndürme sırasında Web Görünümünün yeniden yüklenmesini engellemenin en iyi yolu.

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

Bunu akılda tutarak, onCreate () yönünü her değiştirdiğinizde çağrılmasını önlemek için, android:configChanges="orientation|screenSize" to the AndroidManifest.

ya da sadece ..

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

3

Bir uzlaşma, rotasyonu önlemektir. Etkinliği yalnızca Dikey yönelim için düzeltmek için bunu ekleyin.

android:screenOrientation="portrait"

Bu aslında birçok durumda işe yarıyor ve uygulamaya karar verdiğim çözüm bu :-)
Abdo

1
hehe, bu bir gereksinim değişikliği
Max Ch

3

Manifest dosyanıza aşağıdaki kod satırlarını yazın - başka hiçbir şey yazmayın. Gerçekten çalışıyor:

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

3

Bunun biraz geç olduğunu anlıyorum, ancak çözümümü geliştirirken kullandığım cevap şu:

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

}

2

Sen kullanmayı deneyebilirsiniz onSaveInstanceState()ve onRestoreInstanceState()çağırmak için Etkinliğini saveState(...)ve restoreState(...)WebView örneğinde.


2

Yıl 2015 ve birçok kişi hala Jellybean, KK ve Lollipop telefonlarında çalışan bir çözüm arıyor. Çok uğraştıktan sonra , yönünüzü değiştirdikten sonra web görünümünü bozulmadan korumanın bir yolunu buldum. Benim stratejim temelde web görünümünü başka bir sınıfta ayrı bir statik değişkende saklamaktır. Ardından, döndürme meydana gelirse, web görünümünü etkinlikten ayırıyorum, yönlendirmenin bitmesini bekliyorum ve web görünümünü yeniden etkinliğe ekliyorum. Örneğin ... önce bunu MANIFEST'inize koyun (keyboardHidden ve klavye isteğe bağlıdır):

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

AYRI BAŞVURU SINIFINDA şunları koyun:

     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'de şunu koyun:

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

Son olarak, basit 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>

Çözümümde geliştirilebilecek birkaç şey var, ancak çok zaman harcadım, örneğin: Paylaşılan Tercihler depolamasını kullanmak yerine Aktivitenin ilk kez başlatılıp başlatılmadığını doğrulamanın daha kısa bir yolu. Bu yaklaşım, web görünümünüzü bozulmadan (afaik), metin kutularını, etiketlerini, kullanıcı arayüzünü, javascript değişkenlerini ve url tarafından yansıtılmayan gezinme durumlarını korur.


1
Konfigürasyon değişikliklerini manuel olarak hallettiğiniz için, neden daha ilk etapta yok edilmeyen Web Görünümü'nü çıkarıp yeniden takmakla uğraşasınız ki?
Fred

@Fred Çünkü Webview tarafından yüklenen web sayfasının içinde çerezler ve HTML5 veya JS ile uygulanan düğmeler ve onay kutularının durumu da dahil olmak üzere Web görünümünün ve içeriğinin tam durumunu korumak istiyorum. Yaptığım tek ayarlama yeniden boyutlandırmak.
Josh

Fred, manifest'te configChanges açıkladığınız için web görünümünü statik bir sınıf aracılığıyla ayırmanıza / yeniden eklemenize gerek olmadığı anlamına geliyordu. Bu şekilde, hiçbir durumda rotasyon sırasında görüşleriniz ve faaliyetleriniz yok olmaz.
Eugene Kartoyev

2

Yapmanız gereken tek şey, bu kodu manifest dosyanıza eklemektir:

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

2

Güncelleme: mevcut strateji, WebView örneğini ayrıldığında parça tutulması yerine Uygulama sınıfına taşımak ve Josh'un yaptığı gibi devam ettirildiğinde yeniden iliştirmektir. Uygulamanın kapanmasını önlemek için, kullanıcı uygulamalar arasında geçiş yaptığında durumu korumak istiyorsanız, ön plan hizmetini kullanmalısınız.

Parçalar kullanıyorsanız, Web Görünümü'nün saklama örneğini kullanabilirsiniz. Web görünümü, sınıfın örnek üyesi olarak korunacaktır. Bununla birlikte, OnCreateView'e web görünümü eklemelisiniz ve onDestroyView'dan önce üst konteyner ile yok edilmesini önlemek için ayırmalısınız.

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

PS Kredileri kcoppock cevabına gider

'SaveState ()' için artık resmi belgelere göre çalışmamaktadır :

Lütfen bu yöntemin artık bu Web Görünümü için görüntü verilerini depolamadığını unutmayın. RestoreState (Bundle) hiçbir zaman çağrılmadıysa, önceki davranış potansiyel olarak dosyaları sızdırabilirdi.


Parçayı korurken setRetainInstance, görünümün (ve dolayısıyla Web Görünümü'nün) hala yok edildiğini unutmayın.
Fred

1
@Fred Bu ifade için bir kaynak sağlayabilir misiniz? Bunu, bir youtube sayfasını görüntüleyen setRetainInstance (true) ile bir parçaya sahip küçük bir uygulamada test ettim ve yönlendirmeyi değiştirirsem, video kesilmediği için görünüm korunacak gibi görünüyor. Görünüşe göre web görünümü yok ediliyor.
Pinkerton

@Rai Bu sadece bir yanlış okumaydı, o zamandan beri cevabı biraz düzenledim (hala bazı ifade düzeltmelerine ihtiyacı var). Mevcut durumla ilgileniyorsanız - bu yöntem işe yarar. Ancak sorun şu ki, Android bellek yetersiz olduğunda uygulamayı öldürüyor. Kullanıcının başka bir uygulamada bir mesajı okuması gereken önemli bir giriş formum var, bu yüzden işlemin kesilmesini önlemek için bildirim ile ön plan hizmetini kullanmak zorunda kaldım. Yine de android hala aktiviteyi ve dolayısıyla tutulan çerçeveyi yok ediyor. Ancak Application sınıfının örneği korunur - bu yüzden şimdi WebView'ı Uygulama'ya taşıyorum.
Boris Treukhov

1
MutableContextWrapper'ı WebView'in temeli olarak da kullanıyorum, bağlamları ekleme ve ayırma etkinliklerine değiştiriyorum. Chromium'un yakınlaştırma kontrollerinde oluşturduğu bir başka büyük sorun, eski etkinliğe referansı kaydeder, bu nedenle Etkinlik yerine Uygulamaya eklenen Web Görünümü ile çözüme yakınlaştırma olmaz. TL; DR; Formunuz o kadar önemli değilse ve uygulama değiştirdikten sonra işleminizin sonlandırılabileceği ve web görünümünün geri yüklenemeyeceği gerçeğiyle yaşayabilirsiniz, korunan çerçeve çözümüyle gidin. Not: Google çalışanlarının tüm widget'ları ile gerçek hayattaki sorunlardan çok uzak olduğunu düşünüyorum ..
Boris Treukhov

1
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);    
}

@Override
protected void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);    
}

Bu yöntemler herhangi bir etkinlikte geçersiz kılınabilir, temelde bir etkinlik her oluşturulduğunda / yok edildiğinde değerleri kaydetmenize ve geri yüklemenize izin verir, ekran yönü değiştiğinde etkinlik yok edilir ve arka planda yeniden oluşturulur, böylece bu yöntemleri kullanabilirsiniz. değişiklik sırasında geçici saklama / geri yükleme durumlarına.

Aşağıdaki iki yöntemi daha derinlemesine incelemeli ve çözümünüze uyup uymadığını görmelisiniz.

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



1

Benim için işe yarayan tek şey bu (kaydetme örneği durumunu bile kullandım onCreateViewama o kadar güvenilir değildi).

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 durumu için bir Singleton sahibi yaptım. Durum, başvuru süreci devam ettiği sürece korunur.

DÜZENLEME: loadDataWithBaseURLGerekli değildi, sadece

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

Okumama rağmen, bu mutlaka çerezlerle iyi çalışmıyor.


Tekli kullanmak sorunludur, çünkü kullanmanız gereken tek bir örneğiniz olduğunu varsayar.
android geliştiricisi

@androiddeveloper ah. Peki, sizin durumunuzda bu doğru değilse, o zaman gerçekten de bir problemdir. Yalnızca bir WebView örneğim vardı, bu yüzden bu soru benim için bile gelmedi.
EpicPandaForce

1

bunu dene

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

Bu sayfa sorunumu çözdü, ancak ilk başta küçük bir değişiklik yapmam gerekiyor:

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

Bu kısmın benim için ufak bir problemi var bu. İkinci yönelim değişikliğinde uygulama boş gösterici ile sonlandırıldı

bunu kullanarak benim için çalıştı:

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

tam olarak aynı görünüyor. Birincisi çalışmazken ikincisi neden işe yarasın?
android geliştiricisi

0

Bunu denemelisin:

  1. Bu hizmetin içinde bir hizmet oluşturun, Web Görünümünüzü oluşturun.
  2. Hizmeti faaliyetinizden başlatın ve ona bağlanın.
  3. In onServiceConnectedyöntemle, WebView'ı almak ve çağrı setContentViewsizin WebView'ı işlemek için yöntem.

Test ettim ve çalışıyor ancak XWalkView veya GeckoView gibi diğer Web Görünümleri ile çalışmıyor.


Selam! Biraz daha açıklayabilir misin? Teşekkürler
Jaco

1
Peki, web görünümü örneğinizi Activity'den alın ve referansını arka planda çalışan bir hizmete koymaya çalışın. Bu aktiviteyi bir sonraki açışınızda, önce kaydedilen web görünümünü almaya ve oluşturmaya çalışın.
Ramdane Oualitsen

0
@Override
    protected void onSaveInstanceState(Bundle outState )
    {
        super.onSaveInstanceState(outState);
        webView.saveState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState)
    {
        super.onRestoreInstanceState(savedInstanceState);
        webView.restoreState(savedInstanceState);
    }

Cevabınıza birkaç satır açıklama ekleyebilir misiniz?
yacc

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.