Android WebView : 방향 변경 처리


147

문제는 회전 후의 성능입니다. WebView는 페이지를 다시로드해야하며 약간 지루할 수 있습니다.

매번 소스에서 페이지를 다시로드하지 않고 방향 변경을 처리하는 가장 좋은 방법은 무엇입니까?


3
"소스에서 다시로드"한다는 것은 페이지를 다시 다운로드하거나 다시 렌더링한다는 의미입니까?
Jeremy Logan

Blackhex가 참조 한 솔루션으로 내 문제가 해결되었습니다.
Italo Borssatto

6
도대체 어떤 답변도 작동하지
않을

답변:


91

오리엔테이션 변경시 WebView를 다시로드하지 않으려면 Activity 클래스에서 onConfigurationChanged를 대체하십시오.

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

그리고 매니페스트에서 android : configChanges 속성을 설정하십시오.

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

자세한 내용은 다음을 참조 하십시오 :
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange

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


4
테스트했지만 작동하지 않는 것으로 나타났습니다. 아래와 같이 configChanges 속성을 설정하면 작동합니다. android : configChanges = "keyboardHidden | orientation"
virsir

18
전에 여러 번 언급 한 것처럼 실제로 그렇게하지 않는 것이 좋습니다
Matthias

3
Matthias : 이것은 사실이 아닙니다. WebView 용 Javadoc을 참조하십시오.
krtek

이 솔루션에 대해 두 가지주의 할 사항 : 1) WebView를 사용하여 추상 활동이있는 경우 configChanges속성이 서브 클래스 활동에 추가됩니다. 2) 앱이 여러 프로젝트에 의존하는 경우 해당 configChanges속성이 의존성 트리의 상단 (활동 클래스를 포함하는 프로젝트가 아닐 수도 있음).
Amanda S

4
이러한 onConfigurationChanged메서드 재정의는 쓸모가 없습니다.
Miha_x64

69

편집 :이 방법은 더 이상 문서에 명시된대로 작동하지 않습니다


원래 답변 :

이것은 onSaveInstanceState(Bundle outState)활동 을 덮어 쓰고 saveState웹뷰에서 호출하여 처리 할 수 ​​있습니다 .

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

그런 다음 웹보기가 다시 팽창 된 후 onCreate에서 이것을 복구하십시오.

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

26
방향 변경시 작동하지 않습니다. 빈 화면이 표시됩니다. saveState \ restoreState 메소드가 호출되었지만 도움이되지 않습니다.
Oleksii Malovanyi

1
다음은 onCreate 코드 스 니펫입니다. setContentView (R.layout.webview); mWebView = (WebView) findViewById (R.id.webview); if (savedInstanceState == null) {mWebView.getSettings (). setJavaScriptEnabled (true); mWebView.setWebViewClient (new SimpleWebViewClient ()); mWebView.loadUrl (Consts.URL_AUTHORIZATION_OAUTH); } else {mWebView.restoreState (savedInstanceState); }
Oleksii Malovanyi

12
saveState의 문서에서 : 이 메소드는 더 이상이 WebView의 표시 데이터를 저장하지 않습니다. 이전 동작으로 인해 파일이 유출 될 수 있습니다 ...
brillenheini 2016 년

5
- "이 웹보기이 방법은 더 이상 저장 데이터를 표시 있습니다" developer.android.com/reference/android/webkit/WebView.html
스티븐 마크 포드

WebView 양식이 다시로드되지 않도록하기 위해 "이 메소드는 더 이상이 WebView에 대한 표시 데이터를 저장하지 않습니다"라는 작업에 대한 제안이 있습니까?
Lucas P.

24

이에 대한 가장 좋은 대답은 여기에있는 Android 문서를 따르는 것입니다. 기본적으로 이것은 Webview가 다시로드되지 못하게합니다.

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

선택적으로 , onConfigurationChanged활동 을 재정 의하여 이상 현상을 수정 (있는 경우) 할 수 있습니다 .

@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 () 메소드가 필요하지 않습니다. Manifest의 추가 속성 만 있습니다. 내 생각에 이것은 WebView에 의해 기본 지원이 제공 되었기 때문에
이것이이

1
@Booger를 승인하면 onConfigurationChanged () 메서드를 재정의 할 필요가 없습니다. manifest.xml 파일에 android : configChanges = "orientation | screenSize"를 추가하면됩니다.
ozanurkan

5

내가 사용하려고했습니다 onRetainNonConfigurationInstance을 (복귀 웹보기를 다시 그것을 점점) getLastNonConfigurationInstance에서 onCreate 하고 재 할당.

아직 작동하지 않는 것 같습니다. 나는 도울 수 없지만 내가 정말 가까이 있다고 생각합니다! 지금까지 빈 / 백색 배경 WebView를 얻었습니다. 를 . 누군가가 이것을 결승선을 지나서 밀어 낼 수 있기를 바랍니다.

어쩌면 WebView를 전달해서는 안됩니다 . 아마도 WebView 내에서 객체 입니까?

내가 좋아하는 것이 아닌 다른 방법은 활동에서 이것을 설정하는 것입니다.

 android:configChanges="keyboardHidden|orientation"

... 그리고 여기서 거의 아무것도하지 않습니다.

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

작동하지만 모범 사례 로 간주되지 않을 수 있습니다 .

한편, 회전에 따라 자동으로 업데이트하려는 단일 ImageView 도 있습니다 . 이것은 매우 쉬운 것으로 판명되었습니다. 내에서 res폴더, 내가 가진 drawable-landdrawable-port보류 가로 / 세로 변화에, 나는 사용 R.drawable.myimagename에 대한 이미지 뷰 소스와 안드로이드의 "옳은 않습니다"- 야호!

... 구성 변경을 볼 때를 제외하고는 변경되지 않습니다. :(

그래서 나는 확률이 높습니다. onRetainNonConfigurationInstance를 사용 하면 ImageView 회전이 작동하지만 WebView 지속성이 작동 하지 않거나 onConfigurationChanged를 사용 하면 WebView 가 안정적으로 유지되지만 ImageView 는 업데이트되지 않습니다. 무엇을해야합니까?

마지막 참고 사항 : 제 경우에는 방향 강제 적용이 용납되지 않습니다. 우리는 실제로 회전을 정상적으로 지원하고 싶습니다. 안드로이드 브라우저 앱의 작동 방식을 좋아하십시오! ;)


7
onRetainNonConfigurationInstance에서 뷰를 반환해서는 안됩니다. 보기는 활동 컨텍스트에 첨부되므로보기를 저장하면 방향 변경이있을 때마다 모든 수하물을 처리합니다. 보기가 "누설되었습니다". (마지막 단락 : developer.android.com/resources/articles/… 참조 ) onRetainNonConfigurationInstance의 모범 사례는보기 자체가 아니라보기에 필요한 데이터를 저장하는 것입니다.
Declan Shanaghy

3

한 가지 타협은 회전을 피하는 것입니다. 세로 방향의 활동 만 수정하려면 이것을 추가하십시오.

android:screenOrientation="portrait"

이것은 실제로 많은 경우에 작동하며 구현하기로 결정한 솔루션입니다. :-)
Abdo

1
hehe, 이것은 요구 사항 변경입니다
Max Ch

3

방향 변경 및 회전시 WebView 다시로드 방지를 처리하는 가장 좋은 방법입니다.

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

이를 염두에두고 방향을 변경할 때마다 onCreate ()가 호출되지 않도록하려면 추가해야합니다. android:configChanges="orientation|screenSize" to the AndroidManifest.

또는 그냥 ..

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

3

Manifest 파일에 다음 코드 줄을 작성하십시오. 실제로 작동한다:

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

3

조금 늦었지만 고맙지 만 솔루션을 개발할 때 사용한 답변입니다.

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

onSaveInstanceState()onRestoreInstanceState()활동을 사용 하여 WebView 인스턴스 를 호출 saveState(...)하고 시도 할 수 있습니다 restoreState(...).


2

2015 년이며 많은 사람들이 아직도 Jellybean, KK 및 Lollipop 전화에서 작동하는 솔루션을 찾고 있습니다. 이후 많은 어려움을 겪고 난 당신이 방향을 변경 한 후 그대로 웹보기를 보존 할 수있는 방법을 발견했다. 내 전략은 기본적으로 웹보기를 다른 클래스의 별도 정적 변수에 저장하는 것입니다. 그런 다음 회전이 발생하면 활동에서 웹보기를 분리하고 방향이 끝날 때까지 기다렸다가 웹보기를 활동에 다시 연결하십시오. 예를 들어 ... 먼저 이것을 MANIFEST에 넣으십시오 (keyboardHidden 및 키보드는 선택 사항입니다).

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

SEPARATE APPLICATION CLASS에서 다음을 입력하십시오.

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

활동에서 다음을 입력하십시오.

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

마지막으로 간단한 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>

솔루션에서 개선 할 수있는 몇 가지 사항이 있지만 이미 많은 시간을 보냈습니다. 예 : SharedPreferences 스토리지를 사용하는 대신 처음으로 활동이 시작되었는지 확인하는 더 짧은 방법. 이 접근 방식은 URL에 반영되지 않은 그대로의 웹뷰 (afaik), 텍스트 상자, 레이블, UI, 자바 스크립트 변수 및 탐색 상태를 유지합니다.


1
구성 변경을 수동으로 처리하기 때문에 처음부터 WebView가 손상되지 않을 때 WebView를 분리했다가 다시 연결해야하는 이유는 무엇입니까?
Fred

@Fred 쿠키를 포함한 웹뷰의 정확한 상태와 쿠키, 웹뷰에 의해로드 된 웹 페이지 안에 HTML5 또는 JS로 구현 된 버튼과 체크 박스의 상태를 그대로 유지하려고하기 때문입니다. 내가하는 유일한 조정은 크기 조정입니다.
Josh

Fred는 매니페스트에서 configChanges를 선언했을 때 정적 클래스를 통해 webview를 분리하거나 다시 연결할 필요가 없음을 의미했습니다. 이런 식으로 어떤 경우에도 회전 중에 뷰와 활동이 파괴되지 않습니다.
Eugene Kartoyev

2

당신이해야 할 유일한 일은이 코드를 매니페스트 파일에 추가하는 것입니다.

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

2

업데이트 : 현재 전략은 분리 할 때 조각이 유지되지 않고 WebView 인스턴스를 응용 프로그램 클래스로 이동하고 Josh가 재개 할 때 다시 연결하는 것입니다. 응용 프로그램이 닫히지 않도록하려면 사용자가 응용 프로그램간에 전환 할 때 상태를 유지하려면 포 그라운드 서비스를 사용해야합니다.

프래그먼트를 사용하는 경우 WebView의 인스턴스 유지를 사용할 수 있습니다. 웹보기는 클래스의 인스턴스 멤버로 유지됩니다. 그러나 웹 컨테이너를 OnCreateView에 첨부하고 OnDestroyView 전에 분리하여 상위 컨테이너로 파괴되지 않도록해야합니다.

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 크레딧은 kcoppock 답변으로

'SaveState ()'에 대해서는 공식 문서 에 따라 더 이상 작동하지 않습니다. .

이 방법은 더 이상이 WebView의 표시 데이터를 저장하지 않습니다. restoreState (Bundle)가 호출되지 않은 경우 이전 동작으로 인해 파일이 누출 될 수 있습니다.


setRetainInstanceFragment를 유지 하면서 뷰 (및 WebView)는 여전히 파손됩니다.
Fred

1
@Fred 그 진술의 출처를 제공해 줄 수 있습니까? YouTube 페이지를 표시하는 setRetainInstance (true) 조각이있는 작은 응용 프로그램에서 이것을 테스트했으며 방향을 변경하면 비디오가 중단되지 않아보기가 유지되는 것처럼 보입니다. 웹보기가 파괴되는 것처럼 보이지 않습니다.
Pinkerton

@Rai 그것은 단지 오해였습니다. 그 이후로 약간의 대답을 편집했습니다 (여전히 문구 수정이 필요합니다). 현재 상황에 관심이 있다면이 방법이 효과적입니다. 그러나 문제는 메모리가 부족하면 안드로이드가 응용 프로그램을 종료한다는 것입니다. 사용자가 다른 응용 프로그램에서 메시지를 읽어야하는 중요한 입력 양식이 있으므로 프로세스가 종료되지 않도록 알림과 함께 포 그라운드 서비스를 사용해야했습니다. 그러나 안드로이드는 여전히 활동과 따라서 유지 된 프레임을 파괴합니다. 그러나 Application 클래스의 인스턴스는 유지되므로 WebView를 이제 Application으로 옮깁니다.
Boris Treukhov

1
또한 MutableContextWrapper를 WebView의 기반으로 사용하고 컨텍스트를 연결 및 분리시 활동으로 전환합니다. 확대 / 축소 컨트롤에 Chromium이 빌드하는 또 다른 큰 문제는 이전 활동에 대한 참조를 저장하지 않으므로 WebView가 Activity 대신 응용 프로그램에 연결된 솔루션은 확대되지 않습니다. TL; DR; 양식이 그렇게 중요하지 않은 경우 앱 전환 후 프로세스가 종료되고 웹보기가 복원되지 않는 경우 프레임 솔루션이 유지됩니다. 추신 : 저는 또한 구글 직원들이 모든 위젯 가제트와 실제 문제와는 거리가 멀다고 생각합니다.
Boris Treukhov

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

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

이 방법은 모든 활동에서 재정의 될 수 있습니다. 기본적으로 활동을 만들거나 삭제할 때마다 화면 방향이 변경 될 때 활동이 파괴되고 백그라운드에서 다시 생성 될 때마다 기본적으로 값을 저장하고 복원 할 수 있으므로이 방법을 사용할 수 있습니다 변경하는 동안 임시 저장 / 복원 상태로

다음 두 가지 방법을 자세히 살펴보고 이것이 솔루션에 적합한 지 확인해야합니다.

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


1

이전 Activity참조 를 누설 하지 않고 configChanges.. 을 설정 하지 않고이 작업을 수행하는 가장 좋은 솔루션 은 MutableContextWrapper 를 사용하는 것 입니다.

나는 이것을 여기에 구현했다 : https://github.com/slightfoot/android-web-wrapper/blob/48cb3c48c457d889fc16b4e3eba1c9e925f42cfb/WebWrapper/src/com/example/webwrapper/BrowserActivity.java


부작용없이 안정적으로 작동합니까? 이 방법에 대한 많은 정보를 찾지 못했습니다.
craigrs84

1

이것은 나를 위해 일한 유일한 것입니다 (저장 인스턴스 상태를 사용 onCreateView했지만 신뢰할 수는 없었습니다).

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 상태에 대한 Singleton 홀더를 만들었습니다. 응용 프로그램 프로세스가 존재하는 한 상태가 유지됩니다.

편집 : loadDataWithBaseURL필요하지 않았습니다, 그냥 잘 작동했습니다.

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

비록 이것을 읽었지만 쿠키와 잘 작동하지는 않습니다.


사용해야 할 인스턴스가 하나만 있다고 가정하므로 싱글 톤을 사용하는 것은 문제가됩니다.
안드로이드 개발자

@androiddeveloper 아. 글쎄, 그것이 사실이 아니라면, 그것은 실제로 문제입니다. WebView 인스턴스가 하나뿐 이므로이 질문은 나오지 않았습니다.
EpicPandaForce

1

이 시도

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

이 페이지는 내 문제를 해결하지만 처음에는 약간 변경해야합니다.

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

이 부분은 나에게 약간의 문제가 있습니다. 두 번째 방향 변경시 응용 프로그램이 null 포인터로 종료되었습니다.

이것을 사용하여 그것은 나를 위해 일했다 :

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

정확히 같은 것 같습니다. 이전이 작동하지 않는데 왜 두 번째가 작동합니까?
안드로이드 개발자

0

이것을 시도해야합니다 :

  1. 해당 서비스 내에 서비스를 작성하여 WebView를 작성하십시오.
  2. 활동에서 서비스를 시작하고 바인드하십시오.
  3. 에서 onServiceConnected방법, 웹보기를 얻고 호출 setContentView하여 웹보기를 렌더링하는 방법.

나는 그것을 테스트했고 XWalkView 또는 GeckoView와 같은 다른 WebViews에서는 작동하지 않습니다.


안녕하세요! 더 설명해 주시겠습니까? 감사합니다
Jaco

1
자, Webview 인스턴스를 Activity에서 가져 와서 백그라운드에서 실행중인 서비스에 굴절을 넣으십시오. 다음에 해당 활동을 열 때 저장된 웹뷰를 먼저 가져 와서 렌더링하십시오.
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);
    }

답변에 설명을 추가 할 수 있습니까?
yacc

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.