티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

How can I save an activity state using the save instance state?

액티비티 상태 저장하기

 문제 내용 

I've been working on the Android SDK platform, and it is a little unclear how to save an application's state. So given this minor re-tooling of the 'Hello, Android' example:

나는 안드로이드 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);
  }
}

 

I thought it would be enough for the simplest case, but it always responds with the first message, no matter how I navigate away from the app.

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

 

I'm sure the solution is as simple as overriding onPause or something like that, but I've been poking away in the documentation for 30 minutes or so and haven't found anything obvious.

나는 솔루션이 onPause 또는 이와 유사한 것을 재정의하는 것처럼 간단하다고 확신하지만 문서에서 30분 정도 파헤쳐 보았지만 분명한 것을 찾지 못했습니다.

 

 

 

 높은 점수를 받은 Solution 

You need to override onSaveInstanceState(Bundle savedInstanceState) and write the application state values you want to change to the Bundle parameter like this:

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

 

The Bundle is essentially a way of storing a NVP ("Name-Value Pair") map, and it will get passed in to onCreate() and also onRestoreInstanceState() where you would then extract the values from activity like this:

번들은 기본적으로 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");
}

 

Or from a fragment.

아니면 Fragment에서.
@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");
}

 

You would usually use this technique to store instance values for your application (selections, unsaved text, etc.).

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

 

 

 

 가장 최근 달린 Solution 

using Android ViewModel & SavedStateHandle to persist the serializable data

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

 

in layout file

레이아웃 파일로
<?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>

 

Test:

테스트:
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

 

 

출처 : https://stackoverflow.com/questions/151777/how-can-i-save-an-activity-state-using-the-save-instance-state

반응형
댓글
공지사항
최근에 올라온 글