Save 인스턴스 상태를 사용하여 활동 상태를 저장하려면 어떻게합니까?
질문
나는 Android 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);
}
}
나는 그것이 가장 단순한 경우에 충분하다고 생각했지만, 어떻게 앱에서 멀리 떨어져 탐색하는지 상관없이 항상 첫 번째 메시지와 함께 응답합니다.
나는 솔루션이 overriding onpause 또는 그런 것처럼 간단하지만 30 분 정도의 문서에서 멀리 떨어져서 분명한 것을 발견하지 못했습니다.
답변
OnSaveInStanceState (Bundle SavedInStanceState)를 무시하고 다음과 같이 번들 매개 변수로 변경하려는 응용 프로그램 상태 값을 작성해야합니다.
@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 ( "name-value pair") 맵을 저장하는 방법이며 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");
}
일반적 으로이 기술을 사용하여 응용 프로그램의 인스턴스 값 (선택, 저장되지 않은 텍스트 등)을 저장합니다.
답변
SaveDinStanceState는 현재 탐색 또는 선택 정보와 같은 활동의 현재 인스턴스와 관련된 상태를 저장하는 데만 Android가 활동을 파괴하고 재현성하는 경우 이전에 발생할 수 있습니다.OnCreate 및 OnSaveInStanceState에 대한 설명서를 참조하십시오
더 오래 살았던 상태의 경우 SQLite 데이터베이스, 파일 또는 환경 설정을 사용하는 것을 고려하십시오.지속적인 상태 저장을 참조하십시오.
답변
활동에 대한 설명서에 따라 영구 데이터에 대한 OnSaveInStanceState 및 OnRestoreInStanceState를 사용하는 것이 안전하지 않습니다.
문서 상태 ( '활동 라이프 사이클'섹션에서) :
저장하는 것이 중요합니다 대신 onpause ()의 지속적인 데이터 Onsaveinstancestate (번들) 나중에는 그 부분이 아닙니다 라이프 사이클 콜백, 그렇게하지 않을 것입니다 묘사 된 모든 상황에서 호출되었습니다 문서에서.
즉, 저장 / 복원 코드를 onpause () 및 onresume ()의 영구 데이터에 넣으십시오!
더 자세한 설명을 위해 다음은 OnSaveInStanceState () 문서가 있습니다.
이 방법은 활동이 사망 할 수있게되기 전에 호출됩니다. 앞으로 언젠가는 그 상태를 회복 할 수 있습니다.을 위한 예제, 활동 B가 활동 A 앞에서 시작되고 일부에서 포인트 활동 A 자원을 회수하기 위해 사망, 활동 A는 이를 통해 사용자 인터페이스의 현재 상태를 저장할 수있는 기회 메서드가 사용자가 활동 A로 돌아가는 경우 사용자 인터페이스는 OnCreate (Bundle)를 통해 복원 할 수 있습니다. OnRestoreInstancestate (번들).
답변
제 동료는 활동 수명주기 및 상태 정보에 대한 설명, 상태 정보를 저장하는 방법, 상태 정보 저장 및 SharedPreferences에 저장하는 방법을 포함하여 Android 기기에 대한 응용 프로그램 상태를 설명하는 기사를 작성했습니다.여기 그것을보세요.
이 기사는 세 가지 접근법을 다룹니다.
인스턴스 상태 번들을 사용하여 응용 프로그램 수명 (즉, 일시적으로)에 대한 로컬 변수 / 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();
}
답변
이것은 안드로이드 개발의 고전적인 '고치'입니다.여기에 두 가지 문제가 있습니다 :
최소한 레거시 버전 (완전히 확실하지 않은 경우 / 수정 된 경우)에서 개발 중에 응용 프로그램 스택 관리를 크게 복잡하게하는 미묘한 안드로이드 프레임 워크 버그가 있습니다.아래 에이 버그를 논의 할게. 이 문제를 관리하는 '보통'또는 의도 된 방법은 onpause / onresume 및 onsaveinstancestate / onrestoreinstancestate의 이중성으로 복잡한 것입니다.
이러한 모든 스레드에서 브라우징하는 경우 개발자 들이이 두 가지 다른 문제에 대해 동시에 이야기하고있는 많은 시간을 탐색 한 것으로 의심합니다.
첫째, '의도 된'행동을 명확히하기 위해 onsaveInstance와 OnrestoreInstance는 깨지기 쉽고 일시적인 상태만을 위해서만입니다.의도 한 사용법 (내가 말할 수있는 한)은 휴대 전화가 회전 할 때 활동 레크리에이션을 처리하는 것입니다 (오리엔테이션 변경).즉, 의도 된 사용법은 활동이 여전히 논리적으로 '상단에'이지만 시스템에 의해 여전히 재발해야합니다.저장된 번들은 프로세스 / 메모리 / GC 외부에서 유지되지 않으므로 활동이 배경으로 가면 정말로 의지 할 수 없습니다.예, 아마도 귀하의 활동의 기억은 백그라운드로 여행을 살아남고 GC를 이스케이프 할 수있을 것입니다. 그러나 이것은 신뢰할 수 없습니다 (예측 가능도 없음).
따라서 응용 프로그램의 '시작'간에 의미있는 '사용자 진행률'또는 상태가있는 시나리오가있는 경우 지침은 onpause 및 onresume을 사용하는 것입니다.지속적인 저장소를 선택하고 준비해야합니다.
그러나 -이 모든 것을 복잡하게하는 매우 혼란스러운 버그가 있습니다.세부 정보는 다음과 같습니다.
활동 스택은 Eclipse에서 시작될 때 앱 첫 번째 실행 중에 잘못 작동합니다 (# 36907463) 마켓 플레이스 / 브라우저 App 설치 프로그램은 두 번째 인스턴스를 앱 (# 36911210)에서 허용합니다.
기본적으로 응용 프로그램이 SingleTask 플래그로 시작한 다음 나중에 홈 화면이나 실행기 메뉴에서 시작한 다음 이후의 호출로 인해 새 작업이 생성됩니다 ... 효과적으로 두 가지 다른 인스턴스가 있습니다.동일한 스택에 거주하는 ... 매우 이상한 매우 빠릅니다.이것은 개발 중에 앱을 시작할 때 (즉, Eclipse 또는 Intellij에서) 개발자가 많이 실행하는 것처럼 보입니다.뿐만 아니라 일부 앱 스토어 업데이트 메커니즘을 통해서도 사용자에게 영향을 미치므로).
나는 몇 시간 동안 이러한 스레드를 통해 싸우기 전에 내 주요 문제 가이 버그라는 것을 깨달았습니다. 의도 된 프레임 워크 동작이 아닙니다.훌륭한 쓰기 및 해결 방법 (업데이트 : 아래 참조)이 답변에서 사용자 @kaciula에서 인 것 같습니다.
홈 키를 누릅니다
2013 년 6 월 업데이트 : 몇 달 후, 마침내 '올바른'솔루션을 발견했습니다.Stateful StartwAlp Flags를 직접 관리 할 필요가 없습니다.이 프레임 워크에서이를 감지하고 보석금을 적절하게 탐지 할 수 있습니다.나는 이것을 내 런치 장세의 시작 부분에 사용합니다 .OnCreate :
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에 저장되어야한다고 생각합니다.
기본 설정이나 SQLite와 같은 일부 영구 저장소에 저장해야합니다.
출처:https://stackoverflow.com/questions/151777/how-can-i-save-an-activity-state-using-the-save-instance-state
최근댓글