다양한 Android 시스템 작업은 프래그먼트 상태에 영향을 미칠 수 있습니다. Android 프레임워크에서는 사용자 상태가 저장되도록 프래그먼트와 백 스택을 자동으로 저장하고 복원합니다. 따라서 프래그먼트의 모든 데이터도 저장되고 복원되도록 해야 합니다.
다음 표는 프래그먼트가 상태를 잃게 만드는 작업과 함께 다양한 유형��� 상태가 이러한 변경에도 지속되는지를 간략하게 설명합니다. 표에서 언급된 상태 유형은 다음과 같습니다.
- 변수: 프래그먼트의 로컬 변수
- 뷰 상태: 프래그먼트의 뷰 하나 이상에서 소유한 모든 데이터
- SavedState:
onSaveInstanceState()
에 저장되어야 하는 이 프래그먼트 인스턴스에 고유한 데이터 - NonConfig: 서버 또는 로컬 저장소와 같은 외부 소스에서 가져온 데이터 또는 커밋된 후 서버에 전송되는 사용자 생성 데이터
변수는 종종 SavedState와 동일하게 간주되지만 다음 표에서는 두 가지를 구별하여 다양한 작업이 각각에 미치는 영향을 보여 줍니다.
작업 | 변수 | 뷰 상태 | SavedState | NonConfig |
---|---|---|---|---|
백 스택에 추가됨 | ✓ | ✓ | x | ✓ |
구성 변경 | x | ✓ | ✓ | ✓ |
프로세스 중단/재생성 | x | ✓ | ✓ | ✓* |
백 스택에 추가되지 않고 삭제됨 | x | x | x | x |
호스팅 완료됨 | x | x | x | x |
* NonConfig 상태는 ViewModel의 저장된 상태 모듈을 사용하여 프로세스 종료 시에도 유지될 수 있습니다.
표 1: 프래그먼트를 파괴하는 다양한 작업과 이러한 작업이 여러 상태 유형에 미치는 영향
구체적인 예를 살펴보겠습니다. 임의의 문자열을 생성하여 TextView
에 표시하고 친구에게 전송하기 전에 문자열을 수정하는 옵션을 제공하는 화면을 생각해 보세요.
이 예에서는 사용자가 수정 버튼을 누르면 앱에서 사용자가 메시지를 수정할 수 있는 EditText
뷰를 표시한다고 가정합니다. 사용자가 취소를 클릭하면 EditText
뷰가 지워지고 공개 상태가 View.GONE
으로 설정되어야 합니다. 이러한 화면이 원활하게 작동하려면 다음과 같은 4가지 데이터 관리가 필요합니다.
데이터 | 유형 | 상태 유형 | 설명 |
---|---|---|---|
seed |
Long |
NonConfig | 새로운 좋은 동작을 무작위로 생성하는 데 사용되는 시드입니다. ViewModel 이 만들어지면 생성됩니다. |
randomGoodDeed |
String |
SavedState + 변수 | 프래그먼트가 맨 처음 만들어질 때 생성됩니다.
randomGoodDeed 는 프로세스 종료 및 재생성 후에도 사용자가 동일한 임의의 좋은 동작을 볼 수 있도록 저장됩니다. |
isEditing |
Boolean |
SavedState + 변수 | 불리언 플래그는 사용자가 수정을 시작하면 true 로 설정됩니다.
isEditing 은 프래그먼트가 다시 만들어질 때 화면의 수정 부분이 계속 표시되도록 저장됩니다. |
수정된 텍스트 | Editable |
뷰 상태(EditText 소유) |
EditText 뷰에서 수정된 텍스트입니다.
EditText 뷰는 사용자의 진행 중인 변경사항이 손실되지 않도록 이 텍스트를 저장합니다. |
표 2: 무작위 텍스트 생성기 앱에서 관리해야 하는 상태입니다.
다음 섹션에서는 파괴적인 작업을 통해 데이터 상태를 올바르게 관리하는 방법을 설명합니다.
뷰 상태
뷰는 자체 상태를 관리합니다. 예를 들어 뷰에서 사용자 입력을 수락하면 이 입력을 저장하고 복원하여 구성 변경을 처리하는 것은 뷰가 책임집니다. Android 프레임워크에서 제공하는 모든 뷰에는 자체 onSaveInstanceState()
및 onRestoreInstanceState()
의 구현이 있으므로 프래그먼트 내에서 뷰 상태를 관리하지 않아도 됩니다.
예를 들어 이전 시나리오에서는 수정된 문자열이 EditText
에 보관됩니다. EditText
는 표시하는 텍스트의 값뿐 아니라 선택된 텍스트의 시작 및 끝과 같은 기타 세부정보를 알고 있습니다.
뷰 상태를 유지하려면 뷰에 ID가 필요합니다. 이 ID는 프래그먼트와 프래그먼트의 뷰 계층 구조 내에서 고유해야 합니다. ID가 없는 뷰는 상태를 유지할 수 없습니다.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
표 1에서 언급했듯이 뷰는 프래그먼트를 삭제하거나 호스트를 제거하지 않는 모든 작업을 통해 ViewState
를 저장하고 복원합니다.
SavedState
프래그먼트는 프래그먼트의 작동 방식에 필수적인 소량의 동적 상태를 관리합니다. Fragment.onSaveInstanceState(Bundle)
를 사용하여 쉽게 직렬화된 데이터를 유지할 수 있습니다.
Activity.onSaveInstanceState(Bundle)
와 마찬가지로 번들에 배치하는 데이터는 구성 변경과 프로세스 종료 및 재생성을 통해 유지되고 프래그먼트의 onCreate(Bundle)
, onCreateView(LayoutInflater, ViewGroup, Bundle)
, onViewCreated(View, Bundle)
메서드에서 사용할 수 있습니다.
이전 예를 계속 진행하면 randomGoodDeed
는 사용자에게 표시되는 동작이고 isEditing
은 프래그먼트가 EditText
를 표시하는지 숨기는지 판단하는 플래그입니다. 이 저장된 상태는 다음 예와 같이 onSaveInstanceState(Bundle)
를 사용하여 유지해야 합니다.
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
자바
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
onCreate(Bundle)
에서 상태를 복원하려면 번들에서 저장된 값을 검색합니다.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
자바
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
표 1에서 언급했듯이 변수는 프래그먼트가 백 스택에 배치되면 유지됩니다. 변수를 저장된 상태로 취급하면 파괴적인 작업이 수행되어도 유지됩니다.
NonConfig
NonConfig 데이터는 프래그먼트 외부(예: ViewModel
)에 배치해야 합니다. 위의 예에서 seed
(NonConfig 상태)는 ViewModel
에서 생성됩니다.
상태를 유지하는 로직은 ViewModel
에서 소유합니다.
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
자바
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
ViewModel
클래스는 기본적으로 화면 회전과 같은 구성 변경에도 데이터를 유지할 수 있으며 프래그먼트가 백 스택에 배치되면 메모리에 유지됩니다. 프로세스 종료 및 재생성 후 ViewModel
이 다시 생성되고 새 seed
가 생성됩니다. SavedState
모듈을 ViewModel
에 추가하면 ViewModel
이 프로세스 종료 및 재생성을 통해 간단한 상태를 유지할 수 있습니다.
추가 리소스
프래그먼트 상태 관리에 관한 자세한 내용은 다음 추가 리소스를 참고하세요.
Codelab
- 수명 주기 인식 구성요소 Codelab