programing

인스턴스 상태 저장을 사용하여 활동 상태를 저장하려면 어떻게 해야 합니까?

abcjava 2023. 6. 5. 23:31
반응형

인스턴스 상태 저장을 사용하여 활동 상태를 저장하려면 어떻게 해야 합니까?

안드로이드 SDK 플랫폼에서 작업을 해왔는데, 애플리케이션 상태를 저장하는 방법이 조금 불분명합니다.'Hello, Android'의 예를 들어보면 다음과 같습니다.

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

가장 간단한 경우에는 충분할 것이라고 생각했지만, 앱에서 어떻게 탐색하든 항상 첫 번째 메시지로 응답합니다.

그 를 정하는 것만큼 간단하다고 확신합니다.onPause그런 것도 있지만, 30분 정도 문서를 뒤적여 봤는데 뚜렷한 것을 못 찾았어요.

오버라이드해야 합니다.onSaveInstanceState(Bundle savedInstanceState)하고자 하는 을 변할응프상값기을다니록합으로 .Bundle다음과 같은 매개 변수:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

이며, "NVP("-값 쌍 맵을는며방이, "다로전다니"로 됩니다.onCreate()그리고 또한onRestoreInstanceState()여기서 다음과 같은 활동에서 값을 추출할 수 있습니다.

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

아니면 파편에서.

@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
    super.onViewStateRestored(savedInstanceState);
    // Restore UI state from the savedInstanceState.
    // This bundle has also been passed to onCreate.
    boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
    double myDouble = savedInstanceState.getDouble("myDouble");
    int myInt = savedInstanceState.getInt("MyInt");
    String myString = savedInstanceState.getString("MyString");
}

일반적으로 이 기법을 사용하여 응용 프로그램의 인스턴스 값(선택 항목, 저장되지 않은 텍스트 등)을 저장합니다.

savedInstanceStateAndroid가 활동을 파괴하고 다시 생성할 경우 이전과 동일하게 돌아올 수 있도록 현재 탐색 또는 선택 정보와 같은 활동의 현재 인스턴스와 관련된 상태를 저장하기 위한 것입니다.및 에 대한 설명서를 참조하십시오.

수명이 더 긴 상태의 경우 SQLite 데이터베이스, 파일 또는 환경설정을 사용하는 것이 좋습니다.영구 상태 저장을 참조하십시오.

사용하는 은 안전하지 않습니다.onSaveInstanceState그리고.onRestoreInstanceState 활동 문서에 따라 영구 데이터경우.

이 문서에는 다음과 같이 기술되어 있습니다('활동 라이프사이클' 섹션).

는 에영데저것중이요다니에 합니다.onPause()onSaveInstanceState(Bundle)후자는 라이프사이클 콜백의 일부가 아니기 때문에 설명서에 설명된 모든 상황에서 호출되지 않습니다.

즉, 영구 데이터에 대한 저장/복원 코드를 다음에 넣습니다.onPause()그리고.onResume()!

자세한 내용은 다음과 같습니다.onSaveInstanceState()설명서:

이 메서드는 나중에 작업이 다시 시작될 때 상태를 복원할 수 있도록 작업이 종료되기 전에 호출됩니다.들어 A , 는 이 할 수 , 활동 때의 상태를 할 수 . 자원 회수를 위해 활동 A를 죽인 경우, 활동 A는 이 방법을 통해 사용자 인터페이스의 현재 상태를 저장하여 사용자가 활동 A로 돌아갈 때 다음을 통해 사용자 인터페이스의 상태를 복원할 수 있습니다.onCreate(Bundle)또는onRestoreInstanceState(Bundle).

주기 및 정보에 , , 저장 하여 Android를 작성했습니다.Bundle그리고.SharedPreferences여기를 한번 보세요.

이 문서에서는 세 가지 접근 방식을 다룹니다.

로컬 변수 저장/인스턴스 상태 번들을 사용한 애플리케이션 수명(즉, 일시적)에 대한 UI 제어 데이터

[Code sample – Store state in state bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

로컬 변수 저장/공유 기본 설정을 사용하여 애플리케이션 인스턴스 간(즉, 영구적으로) UI 제어 데이터

[Code sample – store state in SharedPreferences]
@Override
protected void onPause()
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store
  // Commit to storage
  editor.commit();
}

보존된 비구성 인스턴스를 사용하여 애플리케이션 수명 내 작업 간에 메모리에 개체 인스턴스 활성화 유지

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass; // Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance()
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}

이것은 안드로이드 개발의 고전적인 '갓챠'입니다.여기에는 두 가지 문제가 있습니다.

  • Android Framework에는 미묘한 버그가 있으며, 이 버그는 적어도 레거시 버전(수정 여부/시기/방법이 완전히 확실하지 않음)에서 개발 중에 애플리케이션 스택 관리를 크게 복잡하게 만듭니다.이 버그에 대해서는 아래에서 논의하겠습니다.
  • 이 문제를 관리하는 '정상' 또는 의도된 방법은 일시 중지/재개 시와 인스턴스 상태 저장/복원 시의 이중성으로 인해 그 자체가 다소 복잡합니다.인스턴스 상태

이 모든 스레드를 검색해 보면 개발자들이 이 두 가지 다른 문제에 대해 동시에 이야기하는 시간의 대부분이 있을 것으로 생각됩니다.그래서 "이것은 나에게 효과가 없다"는 모든 혼란과 보고가 있습니다.

먼저, '의도된' 동작을 명확히 설명합니다. 인스턴스 저장 및 복원 시인스턴스는 취약하며 일시적인 상태에만 해당됩니다.의도된 용도(내가 알기로는)는 전화기가 회전할 때(방향 변경) 활동 재생을 처리하는 것입니다.즉, 활동이 논리적으로 '최상위' 상태에 있지만 시스템에서 다시 시작해야 하는 경우를 의미합니다.저장된 번들은 프로세스/메모리/GC 외부에서 지속되지 않으므로 작업이 백그라운드로 이동하는 경우에는 실제로 이 번들에 의존할 수 없습니다.예, 활동의 메모리가 백그라운드로 이동하여 GC를 벗어날 수 있지만, 이는 신뢰할 수 없습니다(예측 가능하지도 않습니다).

따라서 애플리케이션의 '실행' 사이에 의미 있는 '사용자 진행률' 또는 상태가 지속되어야 하는 시나리오가 있는 경우에는 일시 중지 및 재개 시 사용하도록 지침을 제공합니다.영구 저장소를 직접 선택하고 준비해야 합니다.

하지만 - 이 모든 것을 복잡하게 만드는 매우 혼란스러운 버그가 있습니다.자세한 내용은 다음과 같습니다.

기본적으로 SingleTask 플래그를 사용하여 응용 프로그램을 시작한 다음 나중에 홈 화면이나 시작 프로그램 메뉴에서 실행하면 이후에 호출하면 새 작업이 만들어집니다.두 개의 서로 다른 앱 인스턴스가 동일한 스택에 상주하게 될 것입니다.그것은 매우 빠르게 이상해집니다.개발 중(이클립스 또는 IntelliJ) 앱을 실행할 때 이러한 현상이 발생하는 것으로 보이며, 따라서 개발자들은 이 문제에 자주 부딪힙니다.또한 일부 앱 스토어 업데이트 메커니즘을 통해 사용자에게도 영향을 미칩니다.

저는 몇 시간 동안 이 스레드들을 뒤지고 나서야 제 주요 문제가 의도된 프레임워크 동작이 아니라 이 버그라는 것을 깨달았습니다.다음 답변에서 사용자 @kaciula가 제공한 훌륭한 기록 및 해결 방법(UPDATE: 아래 참조)이 있습니다.

홈 키 누름 동작

2013년 6월 업데이트: 몇 달 후에 드디어 '올바른' 솔루션을 찾았습니다.상태 저장 시작 앱 플래그를 직접 관리할 필요는 없습니다.이를 프레임워크에서 감지하고 적절히 보석할 수 있습니다.시작 프로그램 활동의 시작 부분에 사용합니다.

if (!isTaskRoot()) {
    Intent intent = getIntent();
    String action = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
        finish();
        return;
    }
}

onSaveInstanceState시스템에 메모리가 필요하여 응용 프로그램을 종료할 때 호출됩니다.사용자가 응용프로그램을 닫기만 하면 호출되지 않습니다. 응용 프로그램 도 그서저애플상션태저생한다각니합다고야장래어되도에 합니다.onPause.

다음과 같은 영구 스토리지에 저장해야 합니다.Preferences◦ SQLite입니다.

두 가지 방법 모두 유용하고 유효하며, 두 가지 모두 다른 시나리오에 가장 적합합니다.

  1. 사용자는 애플리케이션을 종료하고 나중에 다시 열지만 애플리케이션은 마지막 세션의 데이터를 다시 로드해야 합니다. 이를 위해서는 SQLite를 사용하는 것과 같은 지속적인 스토리지 접근 방식이 필요합니다.
  2. 을 전환한 상태로 번들 : 애플리케이션 데이터.onSaveInstanceState()그리고.onRestoreInstanceState()일반적으로 충분합니다.

할 수 있습니다.onResume()또는onCreate()(또는 실제로 모든 라이프사이클 상담에서).이는 바람직한 동작일 수도 있고 아닐 수도 있습니다.한 묶음으로 보관하는 경우InstanceState그런 다음 일시적이며 동일한 사용자 '세션'(세션이라는 용어를 느슨하게 사용함)에서만 사용할 수 있는 데이터를 저장하는 데 적합하지만 '세션' 사이에는 적합하지 않습니다.

모든 것과 마찬가지로 한 가지 접근 방식이 다른 접근 방식보다 더 나은 것은 아닙니다. 단지 어떤 행동이 필요한지 이해하고 가장 적절한 접근 방식을 선택하는 것이 중요합니다.

국가를 구하는 것은 제가 생각하는 한 기껏해야 둔한 일입니다.영구 데이터를 저장해야 하는 경우 SQLite 데이터베이스를 사용하면 됩니다.Android를 사용하면 매우 간단합니다.

이와 같은 것:

import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

    private static final String DATABASE_NAME = "autoMate.db";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SQLiteDatabase db;
    private OpenHelper oh ;

    public dataHelper(Context context) {
        this.context = context;
        this.oh = new OpenHelper(this.context);
        this.db = oh.getWritableDatabase();
    }

    public void close() {
        db.close();
        oh.close();
        db = null;
        oh = null;
        SQLiteDatabase.releaseMemory();
    }


    public void setCode(String codeName, Object codeValue, String codeDataType) {
        Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        String cv = "" ;

        if (codeDataType.toLowerCase().trim().equals("long") == true){
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            cv = String.valueOf(((Date)codeValue).getTime());
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            String.valueOf(codeValue);
        }
        else
        {
            cv = String.valueOf(codeValue);
        }

        if(codeRow.getCount() > 0) //exists-- update
        {
            db.execSQL("update code set codeValue = '" + cv +
                "' where codeName = '" + codeName + "'");
        }
        else // does not exist, insert
        {
            db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
                    "'" + codeName + "'," +
                    "'" + cv + "'," +
                    "'" + codeDataType + "')" );
        }
    }

    public Object getCode(String codeName, Object defaultValue){

        //Check to see if it already exists
        String codeValue = "";
        String codeDataType = "";
        boolean found = false;
        Cursor codeRow  = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        if (codeRow.moveToFirst())
        {
            codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
            codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
            found = true;
        }

        if (found == false)
        {
            return defaultValue;
        }
        else if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (long)0;
            }
            return Long.parseLong(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (int)0;
            }
            return Integer.parseInt(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            if (codeValue.equals("") == true)
            {
                return null;
            }
            return new Date(Long.parseLong(codeValue));
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            if (codeValue.equals("") == true)
            {
                return false;
            }
            return Boolean.parseBoolean(codeValue);
        }
        else
        {
            return (String)codeValue;
        }
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE IF  NOT EXISTS code" +
            "(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }
}

그 후 간단한 통화

dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState", "safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;

답을 찾은 것 같아요.간단한 말로 제가 한 일을 말씀드리겠습니다.

활동 1과 활동 2의 두 가지 활동이 있다고 가정하고 활동 1에서 활동 2(활동 2에서 몇 가지 작업을 수행했습니다)로 이동하고 활동 1의 버튼을 클릭하여 다시 활동 1로 돌아갑니다.이제 이 단계에서 저는 활동 2로 돌아가고 싶었고 마지막으로 활동 2를 떠났을 때와 같은 상태로 활동 2를 보고 싶습니다.

위 시나리오에서 제가 한 것은 매니페스트에서 다음과 같은 변경을 한 것입니다.

<activity android:name=".activity2"
          android:alwaysRetainTaskState="true"      
          android:launchMode="singleInstance">
</activity>

버튼의 활동 1에서 클릭 이벤트는 다음과 같습니다.

Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setClassName(this,"com.mainscreen.activity2");
startActivity(intent);

활동 2 버튼을 클릭하면 이벤트가 표시됩니다.

Intent intent=new Intent();
intent.setClassName(this,"com.mainscreen.activity1");
startActivity(intent);

이제 활동 2에서 변경한 내용이 손실되지 않으며 이전과 동일한 상태에서 활동 2를 볼 수 있습니다.

저는 이것이 답이고 이것이 저에게 잘 맞는다고 믿습니다.제가 틀렸다면 고쳐주세요.

onSaveInstanceState()데이터의 경우(는 인데 단경우의터이restored시위단(경우▁in▁for▁(:)onCreate()/onRestoreInstanceState()),onPause()데이터의 경우(에 표시됨)onResume() Android 문서:

onSaveInstanceState()는 Android에서 활동이 중지 중인 경우 호출되며 활동이 재개되기 전에 종료될 수 있습니다!즉, 활동을 다시 시작할 때 동일한 상태로 다시 초기화하는 데 필요한 모든 상태를 저장해야 합니다.이 번들은 onCreate() 메서드에 해당하며 실제로 onCreate() 메서드에서 전달된 저장된 InstanceState 번들은 onSaveInstanceState() 메서드에서 outState로 구성하는 번들과 동일합니다.

onPause()와 onResume()도 무료 방법입니다.onPause()는 활동이 종료될 때 항상 호출됩니다(예: 종료() 호출).이를 사용하여 현재 노트를 데이터베이스에 다시 저장합니다.모범 사례는 onPause() 중에 해제할 수 있는 모든 리소스를 해제하여 수동 상태일 때 리소스를 적게 차지하는 것입니다.

.onSaveInstanceState()활동이 백그라운드로 이동할 때 호출됩니다.

문서의 인용: "이 방법은 활동이 나중에 언제 돌아올 때 상태를 복구할 수 있도록 활동이 삭제되기 전에 호출됩니다."출처

는 보일러 를 줄이기 위해 과 같은 보일러 플레이트를 합니다.interface그리고.class에읽쓰/▁a/에 읽다/Bundle인스턴스 상태를 저장합니다.


먼저 인스턴스 변수에 주석을 달 때 사용할 인터페이스를 만듭니다.

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.FIELD
})
public @interface SaveInstance {

}

그런 다음 반사를 사용하여 값을 번들에 저장할 클래스를 만듭니다.

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * Save and load fields to/from a {@link Bundle}. All fields should be annotated with {@link
 * SaveInstance}.</p>
 */
public class Icicle {

    private static final String TAG = "Icicle";

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #load(Bundle, Object)
     */
    public static void save(Bundle outState, Object classInstance) {
        save(outState, classInstance, classInstance.getClass());
    }

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #load(Bundle, Object, Class)
     */
    public static void save(Bundle outState, Object classInstance, Class<?> baseClass) {
        if (outState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    field.setAccessible(true);
                    String key = className + "#" + field.getName();
                    try {
                        Object value = field.get(classInstance);
                        if (value instanceof Parcelable) {
                            outState.putParcelable(key, (Parcelable) value);
                        } else if (value instanceof Serializable) {
                            outState.putSerializable(key, (Serializable) value);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not added to the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #save(Bundle, Object)
     */
    public static void load(Bundle savedInstanceState, Object classInstance) {
        load(savedInstanceState, classInstance, classInstance.getClass());
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #save(Bundle, Object, Class)
     */
    public static void load(Bundle savedInstanceState, Object classInstance, Class<?> baseClass) {
        if (savedInstanceState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    String key = className + "#" + field.getName();
                    field.setAccessible(true);
                    try {
                        Object fieldVal = savedInstanceState.get(key);
                        if (fieldVal != null) {
                            field.set(classInstance, fieldVal);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not retrieved from the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

}

사용 예:

public class MainActivity extends Activity {

    @SaveInstance
    private String foo;

    @SaveInstance
    private int bar;

    @SaveInstance
    private Intent baz;

    @SaveInstance
    private boolean qux;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Icicle.load(savedInstanceState, this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Icicle.save(outState, this);
    }

}

참고: 이 코드는 Android라는 라이브러리 프로젝트에서 수정되었습니다.MIT 라이센스로 라이센스가 부여된 자동 배선.

반면에 나는 일반적으로 더 이상 사용하지 않습니다.

Bundle savedInstanceState & Co

라이프 사이클은 대부분의 활동에서 너무 복잡하고 필요하지 않습니다.

그리고 구글은 스스로도 신뢰할 수 없다고 말합니다.

환경설정에서 변경사항을 즉시 저장할 수 있습니다.

 SharedPreferences p;
 p.edit().put(..).commit()

공유 기본 설정은 번들과 유사하게 작동합니다.그리고 자연스럽게 그리고 처음에는 그러한 가치들이 선호도로부터 읽혀져야 합니다.

복잡한 데이터의 경우 기본 설정 대신 SQLite를 사용할 수 있습니다.

이 개념을 적용할 때 활동은 재부팅 사이에 처음 열린 상태인지, 백스택으로 인해 다시 열린 상태인지에 관계없이 마지막으로 저장된 상태를 계속 사용합니다.

원래 질문에 직접 답변합니다. 활동이 다시 생성되지 않으므로 저장된 인스턴스 상태가 null입니다.

활동은 다음과 같은 경우에만 상태 번들로 다시 작성됩니다.

  • 새 활동 인스턴스를 만들어야 하는 방향 또는 전화 언어 변경과 같은 구성 변경.
  • OS가 활동을 파괴한 후 백그라운드에서 앱으로 돌아갑니다.

Android는 메모리 부담이 있거나 백그라운드에서 장시간 작업한 후 백그라운드 작업을 파괴합니다.

hello world 예제를 테스트할 때 몇 가지 방법으로 활동을 종료하고 복귀할 수 있습니다.

  • 뒤로 버튼을 누르면 활동이 완료됩니다.앱을 다시 시작하는 것은 완전히 새로운 사례입니다.백그라운드에서 다시 시작하지 않습니다.
  • 홈 버튼을 누르거나 작업 전환기를 사용하면 활동이 백그라운드로 이동합니다.Create에서 응용프로그램으로 다시 이동할 때는 활동을 삭제해야 하는 경우에만 호출됩니다.

대부분의 경우 홈을 누른 다음 앱을 다시 시작하면 활동을 다시 만들 필요가 없습니다.메모리에 이미 있으므로 Create()가 호출되지 않습니다.

설정 -> 개발자 옵션 아래에 "활동 유지 안 함"이라는 옵션이 있습니다.활성화되면 Android는 항상 활동을 삭제하고 백그라운드에서 재생성합니다.최악의 경우 시나리오를 시뮬레이션하므로 개발 시 활성화된 상태로 두는 것이 좋습니다.(항상 활동을 재활용하는 낮은 메모리 장치).

다른 답변은 상태를 저장하는 올바른 방법을 알려준다는 점에서 가치가 있지만, 왜 코드가 예상한 방식으로 작동하지 않는지에 대한 답변을 제대로 받지 못했다는 느낌이 들었습니다.

onSaveInstanceState(bundle)그리고.onRestoreInstanceState(bundle)메소드는 화면을 회전하는 동안에만 데이터 지속성에 유용합니다(방향 변경).
.onSaveInstanceState()메서드가 호출되지만onCreate(bundle)그리고.onRestoreInstanceState(bundle)다시 호출되지 않습니다.
지속성을 높이려면 공유 환경설정을 사용합니다.이 기사 읽기

문제는 애플리케이션 수명 동안(즉, 동일한 애플리케이션 내에서 다른 하위 작업을 시작하고 장치를 회전하는 등의 단일 실행) 지속성이 필요하다는 것이었습니다.저는 위의 답변들을 다양하게 조합해 보았지만 모든 상황에서 제가 원하는 것을 얻지 못했습니다.결국 제게 도움이 된 것은 생성 중에 저장된 인스턴스 상태에 대한 참조를 얻는 것이었습니다.

mySavedInstanceState=savedInstanceState;

필요할 때 변수의 내용을 얻기 위해 다음과 같이 사용합니다.

if (mySavedInstanceState !=null) {
   boolean myVariable = mySavedInstanceState.getBoolean("MyVariable");
}

사용합니다onSaveInstanceState그리고.onRestoreInstanceState때 변수를 내 할 수도 있을 것 위에서제예변때사변저것수있같다수장여를을니습할도용하용법사방을내경안될만했지변수가예▁as▁to▁when: ▁the사용습(같다니것e▁variable▁my).putBoolean)

허용된 답변이 맞긴 하지만, Icepick이라는 라이브러리를 사용하여 Android에서 활동 상태를 더 빠르고 쉽게 저장할 수 있는 방법이 있습니다.Icepick은 상태 저장 및 복원에 사용되는 모든 상용판 코드를 처리하는 주석 처리기입니다.

Icepick으로 이와 같은 작업 수행:

class MainActivity extends Activity {
  @State String username; // These will be automatically saved and restored
  @State String password;
  @State int age;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

이 작업을 수행하는 것과 동일합니다.

class MainActivity extends Activity {
  String username;
  String password;
  int age;

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putString("MyString", username);
    savedInstanceState.putString("MyPassword", password);
    savedInstanceState.putInt("MyAge", age); 
    /* remember you would need to actually initialize these variables before putting it in the
    Bundle */
  }

  @Override
  public void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    username = savedInstanceState.getString("MyString");
    password = savedInstanceState.getString("MyPassword");
    age = savedInstanceState.getInt("MyAge");
  }
}

은 이스픽상저모장객함작동께다니합체든와아는하태은으로 를 저장하는 와도 작동할 입니다.Bundle.

활동이 생성될 때 해당 활동은 Create() 메서드로 호출됩니다.

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

savedInstanceState는 처음으로 null인 번들 클래스의 개체이지만 다시 생성될 때 값이 포함됩니다.활동의 상태를 저장하려면 인스턴스 상태 저장()을 재정의해야 합니다.

   @Override
    protected void onSaveInstanceState(Bundle outState) {
      outState.putString("key","Welcome Back")
        super.onSaveInstanceState(outState);       //save state
    }

값을 outState와 같은 "outState" 번들 개체에 넣습니다.String("key", "Welcome Back")을 입력하고 super를 호출하여 저장합니다.활동이 파괴될 경우 상태는 번들 개체에 저장되며, 생성() 또는 복원 시 재생 후 복원할 수 있습니다.인스턴스 상태()입니다.생성 시() 및 복원 시에 번들이 수신됨인스턴스 상태()가 동일합니다.

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

          //restore activity's state
         if(savedInstanceState!=null){
          String reStoredString=savedInstanceState.getString("key");
            }
    }

또는

  //restores activity's saved state
 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
      String restoredMessage=savedInstanceState.getString("key");
    }

이 변경사항을 구현하는 방법은 기본적으로 두 가지가 있습니다.

  1. 용사를 onSaveInstanceState()그리고.onRestoreInstanceState().
  2. 매스로토페에서.android:configChanges="orientation|screenSize".

저는 두 번째 방법을 사용하는 것을 추천하지 않습니다.제 경험 중 하나는 세로에서 가로로 회전하는 동안 장치 화면의 절반이 검은색으로 변했기 때문입니다.

위에서 언급한 첫 번째 방법을 사용하면 방향이 변경되거나 구성이 변경될 때 데이터를 유지할 수 있습니다.저장된 인스턴스 상태 개체 내에 모든 유형의 데이터를 저장할 수 있는 방법을 알고 있습니다.

예:Json 개체를 유지하려면 사례를 고려하십시오.게터 및 세터를 사용하여 모델 클래스를 만듭니다.

class MyModel extends Serializable{
JSONObject obj;

setJsonObject(JsonObject obj)
{
this.obj=obj;
}

JSONObject getJsonObject()
return this.obj;
} 
}

이제 onCreate 및 saveInstanceState 메서드의 활동에서 다음을 수행합니다.다음과 같이 표시됩니다.

@override
onCreate(Bundle savedInstaceState){
MyModel data= (MyModel)savedInstaceState.getSerializable("yourkey")
JSONObject obj=data.getJsonObject();
//Here you have retained JSONObject and can use.
}


@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Obj is some json object 
MyModel dataToSave= new MyModel();
dataToSave.setJsonObject(obj);
oustate.putSerializable("yourkey",dataToSave); 

}

다음은 스티브 모즐리의 답변(Toolmaker Steve의 답변)에서 나온 의견입니다(Save Instance State vs on Pause, East cost vs West cost saga).

@VVK - 저는 부분적으로 동의하지 않습니다.앱을 종료하는 일부 방법은 OSIS(Save Instance State)에서 트리거되지 않습니다.이는 osIS의 유용성을 제한합니다.OS 리소스를 최소화하기 위해 지원할 가치가 있지만, 앱이 어떻게 종료되었든 사용자를 원래 상태로 되돌리려면 대신 영구 스토리지 접근 방식을 사용해야 합니다.Create에서 번들을 확인하고, 번들이 없으면 영구 스토리지확인합니다.이것은 의사 결정을 중앙 집중화합니다.충돌, 뒤로 버튼 종료 또는 사용자 지정 메뉴 항목 종료에서 복구하거나 사용자가 며칠 후에 설정한 화면으로 돌아갈 수 있습니다.공구 제작자 스티브 '15년 9월 19일 10:38

코틀린 코드:

저장:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState.apply {
        putInt("intKey", 1)
        putString("stringKey", "String Value")
        putParcelable("parcelableKey", parcelableObject)
    })
}

에 다에음그에서.onCreate()또는onRestoreInstanceState()

    val restoredInt = savedInstanceState?.getInt("intKey") ?: 1 //default int
    val restoredString = savedInstanceState?.getString("stringKey") ?: "default string"
    val restoredParcelable = savedInstanceState?.getParcelable<ParcelableClass>("parcelableKey") ?: ParcelableClass() //default parcelable

옵션을 사용하지 않으려면 기본값 추가

상동방가데에 저장된 onCreate()를 저장한 하려면 먼저 먼저데재저인상스합저니다장태야해에를 .SaveInstanceState(Bundle savedInstanceState)방법.

이 파괴될 때 활동이파때될괴때될▁when▁destroy파▁activity활.SaveInstanceState(Bundle savedInstanceState)메서드가 호출되고 저장할 데이터가 저장됩니다.그리고 당신은 똑같이 됩니다.onCreate()활동이 다시 시작될 때.(활동이 파기되기 전에 일부 데이터를 저장했으므로 저장된 인스턴스 상태는 null이 아닙니다.)

코틀린

당신은 해합다니야재를 무시해야 .onSaveInstanceState그리고.onRestoreInstanceState할 수 .

라이프 사이클 그래프

변수 저장

public override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)

    // prepare variables here
    savedInstanceState.putInt("kInt", 10)
    savedInstanceState.putBoolean("kBool", true)
    savedInstanceState.putDouble("kDouble", 4.5)
    savedInstanceState.putString("kString", "Hello Kotlin")
}

변수 검색

public override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    val myInt = savedInstanceState.getInt("kInt")
    val myBoolean = savedInstanceState.getBoolean("kBool")
    val myDouble = savedInstanceState.getDouble("kDouble")
    val myString = savedInstanceState.getString("kString")
    // use variables here
}

내 솔루션이 문제인지 확실하지 않지만 바인딩된 서비스를 사용하여 ViewModel 상태를 유지합니다.서비스의 메모리에 저장할 것인지, 아니면 SQLite 데이터베이스에서 지속적으로 검색할 것인지는 요구 사항에 따라 달라집니다.이것이 모든 종류의 서비스가 하는 일이며, 애플리케이션 상태 유지 및 추상적인 공통 비즈니스 로직과 같은 서비스를 제공합니다.

모바일 기기에 내재된 메모리 및 처리 제약 때문에 저는 안드로이드 뷰를 웹 페이지와 유사한 방식으로 처리합니다.페이지는 상태를 유지하는 것이 아니라 응용 프로그램 상태를 표시하고 사용자 입력을 수락하는 것이 유일한 목적인 프레젠테이션 계층 구성 요소입니다.웹 앱 아키텍처의 최근 추세는 페이지가 보기, 도메인 데이터가 모델이고 컨트롤러가 웹 서비스 뒤에 있는 오래된 모델, 보기, 컨트롤러(MVC) 패턴을 사용합니다.Android에서도 동일한 패턴을 사용할 수 있습니다. View는 다음과 같습니다.View, 모델은 도메인 데이터이며 컨트롤러는 Android 바운드 서비스로 구현됩니다.뷰가 컨트롤러와 상호 작용하도록 하려면 뷰를 시작/재개 시 바인딩하고 중지/일시 중지 시 바인딩 해제합니다.

이 접근 방식은 애플리케이션 비즈니스 로직을 모두 서비스로 이동할 수 있다는 점에서 관심 분리 설계 원칙을 적용함으로써 여러 뷰에서 중복된 로직을 줄이고 뷰에서 또 다른 중요한 설계 원칙인 단일 책임(Single Responsibility)을 적용할 수 있다는 추가적인 이점을 제공합니다.

이 문제를 해결하는 간단한 방법은 IcePick을 사용하는 것입니다.

라이브러리를 라를설정다니합리러에 합니다.app/build.gradle

repositories {
  maven {url "https://clojars.org/repo/"}
}
dependencies {
  compile 'frankiesardo:icepick:3.2.0'
  provided 'frankiesardo:icepick-processor:3.2.0'
}

이제 활동에서 상태를 저장하는 방법에 대한 아래의 예를 확인해 보겠습니다.

public class ExampleActivity extends Activity {
  @State String username; // This will be automatically saved and restored

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

활동, 조각 또는 번들에 상태를 직렬화해야 하는 모든 개체(예: 모르타르의 View Presenters)에 대해 작동합니다.

Icepick은 사용자 정의 보기에 대한 인스턴스 상태 코드를 생성할 수도 있습니다.

class CustomView extends View {
  @State int selectedPosition; // This will be automatically saved and restored

  @Override public Parcelable onSaveInstanceState() {
    return Icepick.saveInstanceState(this, super.onSaveInstanceState());
  }

  @Override public void onRestoreInstanceState(Parcelable state) {
    super.onRestoreInstanceState(Icepick.restoreInstanceState(this, state));
  }

  // You can put the calls to Icepick into a BaseCustomView and inherit from it
  // All Views extending this CustomView automatically have state saved/restored
}

이제 Android에서 상태 저장을 위한 ViewModel을 제공하므로, 인스턴스 상태 저장 대신 사용해 보십시오.

안드로이드가 어떤 방법도 시행하지 않고 주를 구하도록 만드는 방법이 있습니다.이 행을 활동의 매니페스트 선언에 추가하기만 하면 됩니다.

android:configChanges="orientation|screenSize"

다음과 같이 표시되어야 합니다.

<activity
    android:name=".activities.MyActivity"
    android:configChanges="orientation|screenSize">
</activity>

여기에서 이 속성에 대한 자세한 정보를 찾을 수 있습니다.

수동으로 처리하는 것보다 Android에서 이 작업을 수행하도록 하는 것이 좋습니다.

Kotlin 솔루션:사용자 지정 클래스의 경우 저장 위치onSaveInstanceState을 당은당신수전수있다니습환할업으로 될 수 .JSON문자열을 지정하여 복원합니다.Gson 및 환변 에 대한▁singleString, Double, Int, Long값 저장 및 복원은 다음과 같습니다.다음 예는 다음을 위한 것입니다.Fragment그리고.Activity:

활동용:

를 데터입력에 합니다.saveInstanceState:

override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        //for custom class-----
        val gson = Gson()
        val json = gson.toJson(your_custom_class)
        outState.putString("CUSTOM_CLASS", json)

        //for single value------
        outState.putString("MyString", stringValue)
        outState.putBoolean("MyBoolean", true)
        outState.putDouble("myDouble", doubleValue)
        outState.putInt("MyInt", intValue)
    }

데이터 복원:

 override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)

    //for custom class restore
    val json = savedInstanceState?.getString("CUSTOM_CLASS")
    if (!json!!.isEmpty()) {
        val gson = Gson()
        testBundle = gson.fromJson(json, Session::class.java)
    }

  //for single value restore

   val myBoolean: Boolean = savedInstanceState?.getBoolean("MyBoolean")
   val myDouble: Double = savedInstanceState?.getDouble("myDouble")
   val myInt: Int = savedInstanceState?.getInt("MyInt")
   val myString: String = savedInstanceState?.getString("MyString")
 }

작시복수있다습에서 할 수 .onCreate 한또.

조각의 경우:

class 업용로으.saveInstanceState:

 override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val gson = Gson()
        val json = gson.toJson(customClass)
        outState.putString("CUSTOM_CLASS", json)
    }

데이터 복원:

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        //for custom class restore
        if (savedInstanceState != null) {
            val json = savedInstanceState.getString("CUSTOM_CLASS")
            if (!json!!.isEmpty()) {
                val gson = Gson()
                val customClass: CustomClass = gson.fromJson(json, CustomClass::class.java)
            }
        }

      // for single value restore
      val myBoolean: Boolean = savedInstanceState.getBoolean("MyBoolean")
      val myDouble: Double = savedInstanceState.getDouble("myDouble")
      val myInt: Int = savedInstanceState.getInt("MyInt")
      val myString: String = savedInstanceState.getString("MyString")
    }

Android View Model 및 SavedStateHandle을 사용하여 직렬화 가능한 데이터 유지

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
        binding.setViewModel(new ViewModelProvider(this).get(ViewModel.class));
        binding.setLifecycleOwner(this);
        setContentView(binding.getRoot());
    }

    public static class ViewModel extends AndroidViewModel {

        //This field SURVIVE the background process reclaim/killing & the configuration change
        public final SavedStateHandle savedStateHandle;

        //This field NOT SURVIVE the background process reclaim/killing but SURVIVE the configuration change
        public final MutableLiveData<String> inputText2 = new MutableLiveData<>();


        public ViewModel(@NonNull Application application, SavedStateHandle savedStateHandle) {
            super(application);
            this.savedStateHandle = savedStateHandle;
        }
    }
}

레이아웃 파일로

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="viewModel"
            type="com.xxx.viewmodelsavedstatetest.MainActivity.ViewModel" />
    </data>

    <LinearLayout xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">


        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:autofillHints=""
            android:hint="This field SURVIVE the background process reclaim/killing &amp; the configuration change"
            android:text='@={(String)viewModel.savedStateHandle.getLiveData("activity_main/inputText", "")}' />

        <SeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress='@={(Integer)viewModel.savedStateHandle.getLiveData("activity_main/progress", 50)}' />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="This field SURVIVE the background process reclaim/killing &amp; the configuration change"
            android:text='@={(String)viewModel.savedStateHandle.getLiveData("activity_main/inputText", "")}' />

        <SeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"
            android:progress='@={(Integer)viewModel.savedStateHandle.getLiveData("activity_main/progress", 50)}' />

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="This field NOT SURVIVE the background process reclaim/killing but SURVIVE the configuration change"
            android:text='@={viewModel.inputText2}' />

    </LinearLayout>
</layout>

테스트:

1. start the test activity
2. press home key to go home
3. adb shell kill <the test activity process>
4. open recent app list and restart the test activity

무엇을 저장하고 무엇을 저장하지 말아야 합니까?

나는 왜 그 텍스트인지 궁금해한 적이 있습니다.EditText방향이 변경되는 동안 자동으로 저장됩니까?이은 여러분을 입니다.', 이대은당위한것입다니신을답자▁well다것니입,▁is위▁answer한.

활동 인스턴스가 삭제되고 시스템이 새 인스턴스(예: 구성 변경)를 다시 생성하는 경우.이전 활동 상태(인스턴스 상태)의 저장된 데이터 집합을 사용하여 재생성을 시도합니다.

인스턴스 상태는 다음에 저장된 키-값 쌍의 모음입니다.Bundle물건.

기본적으로 시스템은 보기 개체를 번들에 저장합니다.

  • 텍스트 입력EditText
  • 스크롤치에서 위치 ListView 타기.

인스턴스 상태의 일부로 저장할 다른 변수가 필요한 경우 오버라이드해야 합니다. onSavedInstanceState(Bundle savedinstaneState)방법.

를 들면, 들면를예,int currentScore 활동에서

데이터를 저장하는 동안 onSavedInstanceState(저장된 인스턴스 상태 번들)에 대한 자세한 정보

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

그래서 실수로 당신이 전화하는 것을 잊었다면.super.onSaveInstanceState(savedInstanceState);기본 동작이 작동하지 않습니다. 편집 텍스트의 텍스트가 저장되지 않습니다.

활동 상태를 복원하려면 어떤 항목을 선택해야 합니까?

 onCreate(Bundle savedInstanceState)

OR

onRestoreInstanceState(Bundle savedInstanceState)

두 방법 모두 동일한 번들 개체를 가져오므로 복원 논리를 어디에 쓰는지는 중요하지 않습니다.은 유한차은점에서onCreate(Bundle savedInstanceState)방법은 후자의 경우에는 필요하지 않지만 null 검사를 해야 합니다.다른 응답에 코드 조각이 이미 있습니다.참고하시면 됩니다.

onRestore에 대한 자세한 정보인스턴스 상태(번들이 인스턴스 상태에 저장됨)

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from the saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
}

상항호출로 하세요.super.onRestoreInstanceState(savedInstanceState);합니다.

보너스

onSaveInstanceState(Bundle savedInstanceState)사용자가 활동으로 돌아가려는 경우에만 시스템에서 호출됩니다.예를 들어, 당신은 X 앱을 사용하고 있는데 갑자기 전화가 걸려옵니다.당신은 발신자 앱으로 이동하고 X 앱으로 돌아갑니다.이 경우에는onSaveInstanceState(Bundle savedInstanceState)메서드가 호출됩니다.

그러나 사용자가 뒤로 단추를 누를 경우 이를 고려해야 합니다.가 다시되므로, 이에는 사용자가 활동에 참여할 의사가 없는 으로 간주됩니다. 따라서 이 경우onSaveInstanceState(Bundle savedInstanceState)시스템에서 호출되지 않습니다.데이터를 저장하는 동안 모든 시나리오를 고려해야 합니다.

관련 링크:

데모입니다.
Android 공식 설명서.

언급URL : https://stackoverflow.com/questions/151777/how-can-i-save-an-activity-state-using-the-save-instance-state

반응형