Android - Prevenindo o recarregamento do WebView ao girar

90

Quando eu giro minha tela, o WebView recarrega a página inteira. Eu não posso ter isso porque parte do meu conteúdo contém material dinâmico / aleatório. Atualmente, quando girada, a tela recarrega a URL original do método loadUrl ().

Alguma ideia do que há de errado com meu código?

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>
marca
fonte
1
A solução simplificada que eu mesmo usei e poderia recomendar está aqui: twigstechtips.blogspot.com/2013/08/…
Andrius Baruckis

Respostas:

104

Acho que o principal problema é que você chama web.loadUrl (webURL); também quando savedInstanceState! = null

EDITAR

Experimentar:

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

EDIT2 : Você também precisa da substituição onSaveInstanceState e 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);
}

Observação: adicione também seu AndroidManifest.xml em sua atividade android: configChanges = "idance | screenSize "Obrigado

Giuseppe
fonte
1
Sim! Isso funciona para mim (após a edição, Tim percebeu!)! Obrigado! Você poderia explicar por que e como isso funciona e por que esses métodos precisavam ser substituídos?
marcar
Uma última coisa, eu realmente preciso da seguinte instrução if: if (savedInstanceState! = Null) ((WebView) findViewById (R.id.web)). RestoreState (savedInstanceState);
marcar
21
isso mantém a mesma página, mas ainda recarrega na rotação da tela
Grasper
2
Isso funciona se eu adicionar a propriedade android: configChanges a <activity> em AndroidManifest, então as duas coisas da sua resposta mais aquela. Aqui está uma resposta melhor que inclui todas as três coisas: stackoverflow.com/a/46849736/454780
trusktr
62

Nenhuma codificação java necessária. use isso em seu arquivo de manifesto.

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

gostar:

<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
fonte
2
de que mudanças você está falando?
Pratik Poddar
seguinte comentário de @Mgamerz .. quando o assunto está girando .. essa é a pior sugestão que você pode dar
Guilherme Oliveira
55
Noooooooooooo. Nem pense em fazer isso. As alterações de configuração não se limitam à rotação. Além disso, o estado da instância pode ser restaurado após voltar da memória insuficiente. O problema aqui é que a configuração não será atualizada corretamente quando você fizer isso. Por favor, ninguém faça isso.
Eric Cochran
6
@EricCochran Você poderia escrever a resposta correta, se souber alguma? A resposta aceita ainda recarrega a página para mim, também perde informações da sessão. Que no meu caso é tipo uau, você liga o telefone - você tem que fazer o login novamente.
Atomosk
Isso pode ser apenas parte de uma resposta completa. Veja este melhor: stackoverflow.com/a/46849736/454780
trusktr
21

na tag (manifesto)

android:configChanges="orientation|screenSize"
01wifi01
fonte
9
Na verdade, não há motivo para substituir o onConfigurationChangedmétodo, pois não há nenhuma funcionalidade personalizada adicionada. Simplesmente fazer a alteração no arquivo de manifesto funcionou para mim.
i2097i
manifesto foi suficiente e voto positivo para adicionar apenasorientation|screenSize
Varun Garg
14

Adicionar android:configChanges="orientation|screenSize"manifesto funciona para mim

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>
Rasel
fonte
Você pode postar o que sua MainActivity faz em relação ao WebView?
trusktr
8

Não acredito que isso funcione mais. No meu caso, restaurar o estado usandoWebView.restore(Bundle savedInstanceState) ainda dispara uma recarga da url.

Olhando para os docs para restoreState()você verá que ele diz:

Se for chamado depois que este WebView teve a chance de construir o estado (carregar páginas, criar uma lista para trás / para frente, etc.), pode haver efeitos colaterais indesejáveis.

e

Observe que este método não restaura mais os dados de exibição para este WebView.

Apoio a @ e4c5 por me apontar a direção certa em sua resposta

E, claro, o curso de ação extremo seria evitar que mudanças de orientação acionassem a destruição / criação de atividades. A documentação sobre como fazer isso está aqui

Ranjeev Mahtani
fonte
6

Adicione este código no Manifest

<activity 
     ...
     android:configChanges="orientation|screenSize">
Confundir
fonte
5

Coloque isso na atividade do arquivo Manifest.xml:

android:configChanges="orientation|screenSize"

Aqui está um exemplo:

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

Substitua o onConfigChangemétodo para evitar recarregar dados na mudança de orientação

em sua atividade no AndroidMainfestarquivo.

android:configChanges="orientation|keyboardHidden" 

e tê-los também nas configurações do WebView

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

Tente isso em seu arquivo de manifesto:

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

Como citado aqui ,

Cuidado: a partir do Android 3.2 (API de nível 13), o "tamanho da tela" também muda quando o dispositivo alterna entre a orientação retrato e paisagem. Portanto, se você quiser evitar reinicializações de tempo de execução devido à mudança de orientação ao desenvolver para API de nível 13 ou superior (conforme declarado pelos atributos minSdkVersion e targetSdkVersion), você deve incluir o valor "screenSize" além do valor "orientação". Ou seja, você deve decalar android: configChanges = "idance | screenSize ". No entanto, se seu aplicativo for direcionado ao nível de API 12 ou inferior, então sua atividade sempre lida com essa mudança de configuração (essa mudança de configuração não reinicia sua atividade, mesmo quando executada em um dispositivo Android 3.2 ou superior).

a configuração android:configChanges="orientation|screenSize"da sua atividade resolverá esse problema.

Além disso, observe o seguinte

Lembre-se: ao declarar sua atividade para lidar com uma alteração de configuração, você é responsável por redefinir todos os elementos para os quais fornece alternativas. Se você declarar sua atividade para lidar com a mudança de orientação e tiver imagens que devem mudar entre paisagem e retrato, você deve reatribuir cada recurso a cada elemento durante onConfigurationChanged ().

Davejoem
fonte
3

Esta solução funciona bem para mim:

(1) Em AndroidManifest.xml, adicione esta linha android: configChanges = "keyboard | keyboardHidden | orientação | screenLayout | uiMode | screenSize | smallestScreenSize"

Assim (e como as respostas acima)

<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) Em seguida, em MainActivity.java, verifique 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) e então:

@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.
fonte
0

Adicione isto em Androidmanifest.xml:

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

Agora, quando uma dessas configurações muda, MyActivitynão reinicia. Em vez disso, MyActivityrecebe uma chamada para onConfigurationChanged().

Adicione isso:

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