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>

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


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>

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"

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>

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


6

Adicione este código no Manifest

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

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>

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

4

Tente isso em seu arquivo de manifesto:

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

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 ().


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

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();
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.