onSavedInstanceState 예제를 사용하는 방법


110

상태를 저장하는 것에 관해서는 혼란 스럽습니다. 그래서 onSaveInstanceState(Bundle)활동이 파괴 되려고 할 때 호출 된다는 것을 알고 있습니다. 그러나 정보를 어떻게 저장하고 원래 상태로 되돌릴 수 onCreate(Bundle savedInstanceState)있습니까? 이 번들이 정보를 복원하는 방법을 이해하지 못합니다. 누군가가 예를 들어 줄 수 있다면 도움이 될 것입니다. 개발자 가이드는 이것을 잘 설명하지 못합니다.

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}

text1.setText (savedInstanceState.getString (savedName));
Spidy 2011-06-29

@Spidy onBackpressed는 어떻습니까? 번들로 이에 대해 어떻게 반응합니까?
tj walker

당신은하지 않을 것입니다. 사용자가 뒤로 버튼을 눌렀을 때. 활동이 종료됩니다. 영구 데이터 저장을 위해 데이터베이스를 사용합니다. 다시 시작된 애플리케이션을 이전 상태로 되돌리려면 번들을 사용하십시오.
Spidy 2011-06-29

답변:


198

Bundle저장하려는 모든 정보에 대한 컨테이너입니다. put * 함수를 사용하여 데이터를 삽입합니다. 다음은 .NET 파일에 데이터를 저장하는 데 사용할 수있는 put 함수의 간단한 목록 Bundle입니다.

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

귀하의 onCreate기능에서 이것은 Bundle프로그램으로 다시 전달됩니다. 애플리케이션이 다시로드되는지 또는 처음으로 시작되는지 확인하는 가장 좋은 방법은 다음과 같습니다.

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

데이터를 다시 가져 오려면 put * 함수처럼 get * 함수를 사용하십시오. 데이터는 이름-값 쌍으로 저장됩니다. 이것은 해시 맵과 같습니다. 키와 값을 제공 한 다음 값을 되돌리려면 키를 제공하면 함수가 값을 가져옵니다. 다음은 간단한 예입니다.

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

저장된 메시지가 화면에 토스트됩니다. 도움이 되었기를 바랍니다.


14
onSaveInstanceState ()는 활동이 일시 중지되기 전에 호출됩니다. 이 잠재적으로 저장 번들에서 검색 할 수 있습니다 파괴 된 후에는 필요로하는 모든 정보를 따라서
디에 데 리크

@Spidy Awesome! 당신은 정말 내가 번들에 대한 모든 것을 이해하게 만들었습니다! 그래서 outState가 savedInstanceState 번들로 다시 전달되었다고 추측합니까? 옳은?
tj walker

네. outState 번들은 savedInstanceState 번들로 다시 전달됩니다.
Spidy

1
@tj walker-또 다른 훌륭한 리소스는 기술 참고서입니다. Pro Android 3는 Amazon에서 얻을 수있는 저렴하지만 광범위한 리소스입니다.
Spidy 2011-06-29

@Spidy 나는 당신이 볼 수 있도록 위의 활동 코드를 게시했습니다. 당신이 제안한대로 내가 내 상태를 저장하고 있는지 알려줄 수 있습니다.
tj walker

34

모든 새로운 Android 개발자가 알아야 할 한 가지 중요한 사항은 위젯 (TextView, Buttons 등)의 모든 정보는 ID를 할당하는 한 Android에서 자동으로 유지된다는 것입니다. 따라서 대부분의 UI 상태가 문제없이 처리됩니다. 다른 데이터를 저장해야하는 경우에만 이것이 문제가됩니다.

에서 안드로이드 문서 도구 :

필요한 유일한 작업은 상태를 저장하려는 각 위젯에 고유 ID (android : id 속성 포함)를 제공하는 것입니다. 위젯에 ID가 없으면 상태를 저장할 수 없습니다.


1
정말 사실인가요? 버튼 textview 및 편집 텍스트가있는 활동이 있기 때문입니다. 응용 프로그램이 파괴되거나 종료되면 모든 것이 원래 상태로 돌아갑니다. 내 응용 프로그램에서 사용자가 버튼을 클릭 할 때마다 textView 텍스트가 변경됩니다.
tj walker

문서가 정확하지 않습니까? 뷰가 자체 정보를 저장 한 적이 없습니다. 최선의 방법은 모든 정보를 직접 저장하는 것입니다.
Spidy 2011-06-29

2
목표가 SaveInstanceState에 정보를 저장하는 것이라면이를 수행 할 장소가 아닙니다. 호출 될 것이라는 보장이 없기 때문입니다 (문서 참조). 대신 데이터베이스, SharedPreferences 등에 써야합니다. 예이 정보는 정확합니다. UI가 이러한 방식으로 지속되는지 테스트하는 가장 좋은 방법은 방향 변경에 따라 디스플레이를 회전하고 onCreate를 다시 실행하고 번들을 사용하여 상태를 복원하는 것입니다.
Keith Adler

@Nissan Fan은 위에서 spidy가 한 것처럼 예를 들어 줄 수 있습니까? sharedprefs와 모든 것? 감사합니다
tj walker

가장 좋은 예는 솔직히 문서에서 나온 것입니다. developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler

6

좋은 정보 : onCreate () 메서드에서 Bundle 객체가 null인지 여부를 확인할 필요가 없습니다. 시스템이 onStart () 메서드 이후에 호출하는 onRestoreInstanceState () 메서드를 사용합니다. 시스템은 복원 할 저장된 상태가있는 경우에만 onRestoreInstanceState ()를 호출하므로 번들이 null인지 여부를 확인할 필요가 없습니다.


5

가게 정보:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

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

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

onCreate-Method에서 정보를 복원하지 않으려면 :

예는 다음과 같습니다 . 활동 재생성

onCreate () 동안 상태를 복원하는 대신 시스템이 onStart () 메서드 이후에 호출하는 onRestoreInstanceState ()를 구현하도록 선택할 수 있습니다. 시스템은 복원 할 저장된 상태가있는 경우에만 onRestoreInstanceState ()를 호출하므로 번들이 null인지 여부를 확인할 필요가 없습니다.

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

// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}

0

기본적으로 onSaveInstanceState (Bundle outBundle)는 번들을 제공합니다. Bundle 클래스를 보면 그 안에 많은 다른 것들을 넣을 수 있음을 알 수 있습니다. 다음에 onCreate ()를 호출 할 때 해당 번들을 인수로 다시 가져옵니다. 그런 다음 값을 다시 읽고 활동을 복원 할 수 있습니다.

EditText가있는 활동이 있다고 가정 해 보겠습니다. 사용자가 그 안에 텍스트를 썼습니다. 그 후 시스템은 onSaveInstanceState ()를 호출합니다. EditText에서 텍스트를 읽고 Bundle.putString ( "edit_text_value", theValue)를 통해 Bundle에 씁니다.

이제 onCreate가 호출됩니다. 제공된 번들이 널이 아닌지 확인합니다. 이 경우 Bundle.getString ( "edit_text_value")을 통해 값을 복원하고 EditText에 다시 넣을 수 있습니다.


0

이것은 추가 정보입니다.

이 시나리오를 상상 해보세요

  1. ActivityA는 ActivityB를 시작합니다.
  2. ActivityB는 새로운 ActivityAPrime을 시작합니다.

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
  3. ActivityAPrime은 ActivityA와 관계가 없습니다.
    이 경우 ActivityAPrime.onCreate ()의 번들은 null이됩니다.

ActivityA와 ActivityAPrime이 다른 활동이 아닌 동일한 활동이어야하는 경우 ActivityB는 startActivity ()를 사용하는 것보다 finish ()를 호출해야합니다.


귀하의 예에서 ActivityA == ActivityA 인스턴스 1이고 ActivityAPrime == ActivityA 인스턴스 2입니까? 또한 "ActivityB는 startActivity ()를 사용하는 것보다 finish ()를 호출해야합니다."라고 말하면 의미 : (1) AcitivityB가 finish ()를 호출 한 다음 나중에 startActivity ()를 사용해야합니까 (2) 아니면 ActivityB가 startActivity ()를 전혀 사용하지 않고 finish ()를 호출해야합니까? 옵션 2를 의미했다면, 누군가가 동일한 activityA instance1을 다시 시작하여 파괴 / 종료되기 전에 포함 된 데이터를로드 할 수 있도록 어떻게 제안 하시겠습니까? 감사합니다
cjayem13 2014-08-16

ActivityA와 ActivityAPrime은 동일한 클래스이지만 다른 인스턴스입니다. 이 시나리오에서 ActivityA는 아직 비즈니스를 완료하지 않았으며 그 중간에 ActivityB를 만들고 시작 했으므로 ActivityB가 완료되면 ActivityA가 나머지 비즈니스를 계속해야합니다. 이 경우 startActivity를 호출하는 것은 잘못되었으며 ActivityA 및 ActiviyAPrime이 동일한 인스턴스가 될 것으로 예상합니다. 그래서 우리는 ActivityA를 다시 시작하지 말아야합니다. 그냥 ActivityB를 끝내고 ActivityA가 작업을 다시 시작하도록합니다 ...
ken

0

데이터가로드되지 않은 savedInstanceState경우 다음 코드를 사용하십시오.
문제는 url 호출이 완전히 완료되지 않았으므로 데이터가로드되었는지 확인한 다음 instanceState 값을 표시합니다.

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.