Android - Verhindern, dass WebView beim Drehen neu geladen wird

87

Wenn ich meinen Bildschirm drehe, lädt das WebView die gesamte Seite neu. Ich kann das nicht haben, da einige meiner Inhalte dynamisches / zufälliges Material enthalten. Derzeit lädt der Bildschirm beim Drehen die ursprüngliche URL von der loadUrl () -Methode neu.

Irgendeine Idee, was mit meinem Code nicht stimmt?

MainActivity.java

package com.mark.myapp;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    WebView web;
    String webURL = "http://www.google.co.uk/";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState != null)
            ((WebView)findViewById(R.id.web)).restoreState(savedInstanceState);

        web = (WebView) findViewById(R.id.web);
        web.getSettings().setJavaScriptEnabled(true);
        web.loadUrl(webURL);
        web.setPadding(0, 0, 0, 0);
        web.getSettings().setLoadWithOverviewMode(true);
        web.getSettings().setUseWideViewPort(true);
        web.getSettings().setSupportZoom(true);
        web.getSettings().setBuiltInZoomControls(true);

        web.setWebViewClient(new HelloWebViewClient());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    private class HelloWebViewClient extends WebViewClient {
        public boolean shouldOverrideUrlLoading(WebView web, String url) {
            web.loadUrl(url);
            return true;
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
            web.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mark.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"

            android:configChanges="orientation|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Kennzeichen
quelle
1
Eine vereinfachte Lösung, die ich selbst verwendet habe und empfehlen kann, ist hier: twigstechtips.blogspot.com/2013/08/…
Andrius Baruckis

Antworten:

102

Ich denke, das Hauptproblem ist, dass Sie web.loadUrl (webURL) aufrufen; auch wenn savedInstanceState! = null

BEARBEITEN

Versuchen:

if (savedInstanceState == null)
{
  web.loadUrl(webURL);
}

EDIT2 : Sie benötigen außerdem die Überschreibung onSaveInstanceState und onRestoreInstanceState.

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

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

Hinweis: Bitte fügen Sie auch Ihre AndroidManifest.xml in Ihrer Aktivität android hinzu: configChanges = "Orientierung | Bildschirmgröße" Danke

Giuseppe
quelle
1
Ja! Das funktioniert bei mir (nach der Bearbeitung hat Tim entdeckt!)! Danke dir! Können Sie möglicherweise erklären, warum und wie dies funktioniert und warum diese Methoden überschrieben werden müssen?
Markieren Sie den
Eine letzte Sache, brauche ich wirklich die folgende if-Anweisung: if (savedInstanceState! = Null) ((WebView) findViewById (R.id.web)). RestoreState (savedInstanceState);
Markieren Sie den
20
Dies behält die gleiche Seite bei,
lädt
2
Dies funktioniert, wenn ich die Eigenschaft android: configChanges zur <Aktivität> in AndroidManifest hinzufüge, also die beiden Dinge aus Ihrer Antwort plus diese. Hier ist eine bessere Antwort, die alle drei Dinge beinhaltet: stackoverflow.com/a/46849736/454780
trusktr
63

Keine Java-Codierung erforderlich. Verwenden Sie dies in Ihrer Manifestdatei.

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

mögen:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.Example.WebviewSample.webviewsample"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>        
</application>
Vettiyanakan
quelle
2
Über welche Änderungen sprichst du?
Pratik Poddar
folgenden @Mgamerz Kommentar .. wenn die Angelegenheit dreht .. Dies ist der schlechteste Vorschlag, den Sie geben können
Guilherme Oliveira
54
Noooooooooooo. Denken Sie nicht einmal darüber nach. Konfigurationsänderungen sind nicht auf die Rotation beschränkt. Der Instanzstatus kann auch wiederhergestellt werden, nachdem aus dem niedrigen Speicher zurückgekehrt wurde. Das Problem hierbei ist, dass die Konfiguration dabei nicht korrekt aktualisiert wird. Bitte, niemand tut das.
Eric Cochran
6
@EricCochran Könnten Sie die richtige Antwort schreiben, wenn Sie eine kennen? Akzeptierte Antwort lädt Seite für mich immer noch neu, außerdem verliert es Sitzungsinformationen. Was in meinem Fall wie Wow ist, du drehst das Telefon - du musst dich erneut anmelden.
Atomosk
Dies kann nur Teil einer vollständigen Antwort sein. Sehen Sie dieses bessere: stackoverflow.com/a/46849736/454780
trusktr
19

im Tag (Manifest)

android:configChanges="orientation|screenSize"
01wifi01
quelle
8
Es gibt eigentlich keinen Grund, die onConfigurationChangedMethode zu überschreiben , da keine benutzerdefinierten Funktionen hinzugefügt wurden. Die Änderung in der Manifestdatei einfach vorzunehmen, hat mir geholfen.
i2097i
Manifest war ausreichend und Upvote für das Hinzufügen nurorientation|screenSize
Varun Garg
14

Das Hinzufügen android:configChanges="orientation|screenSize"in Manifest funktioniert für mich

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>
Rasel
quelle
Können Sie posten, was Ihre MainActivity in Bezug auf WebView tut?
Trusktr
8

Ich glaube nicht, dass das mehr funktionieren wird. In meinem Fall WebView.restore(Bundle savedInstanceState)löst das Wiederherstellen des Status mithilfe von immer noch ein erneutes Laden der URL aus.

Mit Blick auf die Dokumente für restoreState()Sie sagt es sehen werden:

Wenn es aufgerufen wird, nachdem WebView die Möglichkeit hatte, einen Status zu erstellen (Seiten laden, eine Vorwärts- / Rückwärtsliste erstellen usw.), können unerwünschte Nebenwirkungen auftreten.

und

Bitte beachten Sie, dass diese Methode die Anzeigedaten für diese WebView nicht mehr wiederherstellt.

Wir bitten @ e4c5, mich in seiner Antwort in die richtige Richtung zu weisen

Und natürlich wäre die extreme Vorgehensweise, zu verhindern, dass Orientierungsänderungen die Zerstörung / Schaffung von Aktivitäten auslösen. Eine Dokumentation dazu finden Sie hier

Ranjeev Mahtani
quelle
6

Fügen Sie diesen Code in Manifest hinzu

<activity 
     ...
     android:configChanges="orientation|screenSize">
Verwechseln
quelle
4

Überschreiben Sie die onConfigChangeMethode, um ein erneutes Laden von Daten bei Orientierungsänderungen zu vermeiden

auf Ihre Aktivität in AndroidMainfestDatei.

android:configChanges="orientation|keyboardHidden" 

und haben Sie diese auch in Ihren WebView-Einstellungen

webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webview.loadUrl("Your URL To Load");
Sampath Kumar
quelle
4

Versuchen Sie dies in Ihrer Manifestdatei:

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Ajeet Yadav
quelle
4

Fügen Sie dies in die Aktivität der Datei Manifest.xml ein:

android:configChanges="orientation|screenSize"

Hier ist ein Beispiel:

<activity android:name=".MainActivity"
          android:label="@string/app_name"
          android:theme="@style/AppTheme.NoActionBar"
          android:configChanges="orientation|screenSize">
          <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
          </intent-filter>
</activity>
Carlos Alberto Gonzalez
quelle
4

Wie hier zitiert ,

Achtung: Ab Android 3.2 (API-Level 13) ändert sich die "Bildschirmgröße" auch, wenn das Gerät zwischen Hoch- und Querformat wechselt. Wenn Sie also einen Neustart der Laufzeit aufgrund von Orientierungsänderungen bei der Entwicklung für API-Level 13 oder höher (wie durch die Attribute minSdkVersion und targetSdkVersion deklariert) verhindern möchten, müssen Sie zusätzlich zum Wert "Orientierung" den Wert "screenSize" angeben. Das heißt, Sie müssen Android dekalieren: configChanges = "Orientierung | Bildschirmgröße". Wenn Ihre Anwendung jedoch auf API-Stufe 12 oder niedriger abzielt, behandelt Ihre Aktivität diese Konfigurationsänderung immer selbst (diese Konfigurationsänderung startet Ihre Aktivität nicht neu, selbst wenn sie auf einem Android 3.2-Gerät oder höher ausgeführt wird).

Durch Festlegen android:configChanges="orientation|screenSize"Ihrer Aktivität wird dieses Problem behoben.

Beachten Sie auch Folgendes

Denken Sie daran: Wenn Sie Ihre Aktivität für die Bearbeitung einer Konfigurationsänderung deklarieren, müssen Sie alle Elemente zurücksetzen, für die Sie Alternativen bereitstellen. Wenn Sie Ihre Aktivität für die Änderung der Ausrichtung deklarieren und Bilder haben, die zwischen Quer- und Hochformat wechseln sollen, müssen Sie während onConfigurationChanged () jedem Element jede Ressource neu zuweisen.

Davejoem
quelle
3

Diese Lösung funktioniert gut für mich:

(1) Fügen Sie in AndroidManifest.xml diese Zeile hinzu.

So (und wie die obigen Antworten)

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

(2) Überprüfen Sie dann in MainActivity.java savedInstanceState

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mainContext = getApplicationContext();
    ----
    myWebView = (WebView) findViewById(R.id.webView);
    prepareWebView();
    myWebView.addJavascriptInterface(myJavaScriptInterface, "WEB2Android");

    if (savedInstanceState == null) {
        myWebView.post(new Runnable() {
            @Override
            public void run() {
                myWebView.loadUrl("http://www.appbiz.ro/foto_konta");
            }
        });
    }
    ----
}

(3) und dann:

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

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

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    myWebView.restoreState(savedInstanceState);
}
Adrian S.
quelle
0

Fügen Sie dies in Androidmanifest.xml hinzu:

<activity android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">

Wenn sich eine dieser Konfigurationen ändert, MyActivitywird sie nicht neu gestartet. MyActivityErhält stattdessen einen Anruf an onConfigurationChanged().

Füge das hinzu:

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