Android - Ngăn tải lại WebView khi Xoay


90

Khi tôi xoay màn hình của mình, WebView sẽ tải lại toàn bộ trang. Tôi không thể có điều này vì một số nội dung của tôi chứa tài liệu động / ngẫu nhiên. Hiện tại khi xoay màn hình sẽ tải lại URL ban đầu từ phương thức loadUrl ().

Bất kỳ ý tưởng có gì sai với mã của tôi?

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
Giải pháp đơn giản mà tôi sử dụng bản thân mình và có thể đề nghị là ở đây: twigstechtips.blogspot.com/2013/08/...
Andrius Baruckis

Câu trả lời:


103

Tôi nghĩ vấn đề chính là bạn gọi web.loadUrl (webURL); cũng như khi lưuInstanceState! = null

BIÊN TẬP

Thử:

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

EDIT2 : Bạn cũng cần ghi đè onSaveInstanceState và 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);
}

Lưu ý: Cũng vui lòng thêm AndroidManifest.xml của bạn trong Activity android: configChanges = "direction | screenSize" Cảm ơn


1
Đúng! Điều này phù hợp với tôi (sau khi chỉnh sửa, Tim đã phát hiện ra!)! Cảm ơn bạn! Bạn có thể giải thích tại sao và làm thế nào điều này hoạt động và tại sao những phương pháp đó cần ghi đè?
đánh dấu


Một điều cuối cùng, tôi thực sự cần câu lệnh if sau: if (saveInstanceState! = Null) ((WebView) findViewById (R.id.web)). RestoreState (saveInstanceState);
đánh dấu

21
điều này giữ nguyên trang nhưng vẫn tải lại khi xoay màn hình
Grasper

2
Điều này hoạt động nếu tôi thêm thuộc tính android: configChanges vào <activity> trong AndroidManifest, vì vậy hai điều từ câu trả lời của bạn cộng với một thứ. Dưới đây là một câu trả lời tốt hơn bao gồm tất cả ba điều: stackoverflow.com/a/46849736/454780
trusktr

63

Không cần mã hóa java. sử dụng cái này trong tệp kê khai của bạn.

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

giống:

<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
những thay đổi nào bạn đang nói về?
Pratik Poddar

sau @Mgamerz bình luận .. khi vấn đề này được xoay .. đây là gợi ý tồi tệ nhất bạn có thể cho
Guilherme Oliveira

54
Noooooooooooo. Thậm chí không nghĩ đến việc làm điều này. Thay đổi cấu hình không giới hạn ở vòng quay. Ngoài ra, trạng thái phiên bản có thể được khôi phục sau khi trở lại từ bộ nhớ thấp. Vấn đề ở đây là cấu hình sẽ không được cập nhật chính xác khi bạn thực hiện việc này. Xin vui lòng, không ai làm điều này.
Eric Cochran

6
@EricCochran Bạn có thể viết câu trả lời đúng không, nếu bạn biết? Câu trả lời được chấp nhận vẫn tải lại trang cho tôi, nó cũng mất thông tin phiên. Mà trong trường hợp của tôi giống như wow, bạn quay điện thoại - bạn phải đăng nhập lại.
Atomosk

Đây chỉ có thể là một phần của câu trả lời hoàn chỉnh. Thấy điều này tốt hơn một: stackoverflow.com/a/46849736/454780
trusktr

19

trong thẻ (tệp kê khai)

android:configChanges="orientation|screenSize"

8
Thực ra không có lý do gì để ghi đè onConfigurationChangedphương thức vì không có chức năng tùy chỉnh nào được thêm vào. Chỉ cần thực hiện thay đổi trong tệp kê khai đã giúp tôi thành công.
i2097i

bản kê khai đã đủ và ủng hộ chỉ để thêmorientation|screenSize
Varun Garg

14

Thêm android:configChanges="orientation|screenSize"vào tệp kê khai phù hợp với tôi

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>

Bạn có thể đăng những gì MainActivity của bạn làm về WebView không?
trusktr

8

Tôi không tin rằng điều này sẽ hiệu quả nữa. Trong trường hợp của tôi, khôi phục trạng thái bằng cách sử dụngWebView.restore(Bundle savedInstanceState) vẫn kích hoạt tải lại url.

Nhìn vào các tài liệu cho restoreState()bạn sẽ thấy nó nói:

Nếu nó được gọi sau khi WebView này có cơ hội xây dựng trạng thái (tải trang, tạo danh sách lùi / chuyển tiếp, v.v.) thì có thể có những tác dụng phụ không mong muốn.

Xin lưu ý rằng phương pháp này không còn khôi phục dữ liệu hiển thị cho WebView này nữa.

Props to @ e4c5 để chỉ tôi đi đúng hướng trong câu trả lời của anh ấy

Và tất nhiên, quá trình hành động cực đoan sẽ là ngăn những thay đổi về định hướng gây ra sự phá hủy / tạo ra hoạt động. Tài liệu về cách thực hiện việc này ở đây


6

Thêm mã này trong Tệp kê khai

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

4

Ghi đè onConfigChange phương thức để tránh tải lại dữ liệu khi thay đổi hướng

về hoạt động của bạn trong AndroidMainfesthồ sơ.

android:configChanges="orientation|keyboardHidden" 

và có cả những thứ này trong cài đặt WebView của bạn

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

4

Hãy thử điều này trong tệp kê khai của bạn:

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

4

Đặt cái này vào hoạt động tệp Manifest.xml:

android:configChanges="orientation|screenSize"

Đây là một ví dụ:

<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

Như đã trích dẫn ở đây ,

Thận trọng: Bắt đầu với Android 3.2 (API cấp 13), "kích thước màn hình" cũng thay đổi khi thiết bị chuyển đổi giữa hướng dọc và ngang. Do đó, nếu bạn muốn ngăn thời gian chạy khởi động lại do thay đổi hướng khi phát triển API cấp 13 trở lên (như được khai báo bởi thuộc tính minSdkVersion và targetSdkVersion), bạn phải bao gồm giá trị "screenSize" ngoài giá trị "hướng". Đó là, bạn phải decalare android: configChanges = "direction | screenSize". Tuy nhiên, nếu ứng dụng của bạn nhắm mục tiêu API cấp 12 trở xuống, thì hoạt động của bạn luôn tự xử lý thay đổi cấu hình này (thay đổi cấu hình này không khởi động lại hoạt động của bạn, ngay cả khi chạy trên thiết bị Android 3.2 trở lên).

cài đặt android:configChanges="orientation|screenSize" hoạt động của bạn sẽ giải quyết vấn đề này.

Ngoài ra, hãy lưu ý những điều sau

Hãy nhớ: Khi bạn khai báo hoạt động của mình để xử lý thay đổi cấu hình, bạn có trách nhiệm đặt lại bất kỳ phần tử nào mà bạn cung cấp các lựa chọn thay thế. Nếu bạn khai báo hoạt động của mình để xử lý thay đổi hướng và có hình ảnh sẽ thay đổi giữa ngang và dọc, bạn phải gán lại từng tài nguyên cho từng phần tử trong onConfigurationChanged ().


3

Giải pháp này hoạt động tốt đối với tôi:

(1) Trong AndroidManifest.xml thêm dòng này android: configChanges = "keyboard | keyboardHidden | direction | screenLayout | uiMode | screenSize | smallScreenSize"

Như thế này (và thích các câu trả lời ở trên)

<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) Sau đó, trong MainActivity.java, xác minh SaveInstanceState

@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) và sau đó:

@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

Thêm cái này vào Androidmanifest.xml:

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

Bây giờ, khi một trong những cấu hình này thay đổi, MyActivitykhông khởi động lại. Thay vào đó, hãy MyActivitynhận một cuộc gọi tớionConfigurationChanged() .

Thêm điều này:

@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();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.