Configuration change + Multiple screen size 대응 시 키워드 정리

Sehee Jeong·2022년 11월 18일
1
post-thumbnail

Android에서 Configuration change 혹은 Multiple screen size 대응 시 알면 좋은 키워드 공유글이다. 상세한 설명 대신 키워드 위주의 설명이므로 해당 키워드로 검색하면 많은 자료가 나올 것이다.


1. 상태 및 데이터를 저장하는 방법

  • ViewModel Lifecycle

ViewModel 의 lifecycle 은 Activity 의 lifecycle 보다 더 길다. 그림에서도 볼 수 있듯이 Activity 가 단순히 파괴되는 시점이 아닌 완전히 활동을 끝낼 때, ViewModel 의 onCleared() 함수가 호출되고 데이터가 파괴되는 과정을 거친다. 그러므로 configuration change 가 발생할 때 유지해야하는 데이터는 ViewModel에 저장하는 것이 좋다. 또한 ViewModel의 생성자 매개변수로 SavedStateHandle을 정의하여 ViewModel 내부에서 직접 bundle의 데이터를 설정하거나 꺼내 사용하는 방법도 있다.


  • Fragment Lifecycle

configuration change 가 일어날 때, ui state를 유지하고 싶다면 onSavedInstanceState() 를 이용해 bundle 에 state를 담고, 뷰가 재생성된 뒤 onViewStateRestored() 시점에 bundle에 담은 state를 꺼내 셋팅해주는 것이 좋다.


데이터를 ViewModel에 저장할지 bundle을 통해 저장할지 여부는 아래를 참고하면 된다. 둘은"상태를 유지한다"는 관점에서는 동일하지만 언제 사용해야 하는지, 어떤 데이터를 담아야 하는지 차이점을 구분하여 사용하는 것이 좋다.


2. android:configChanges

Manifest의 configChanges 옵션을 적용하면 Activity의 Configuration Changes를 다룰 수 있으며, 다양한 옵션들이 존재한다. configChanges 옵션 유무에 따라 호출되는 lifecycle 에 변동이 생기게 되므로 적절하게 채택하여 사용하면 좋다.

1. 
Given; Manifest에 `android:configChanges` 가 없는 상태
When; Configuration Change 가 발생한 경우
Then; Activity가 재생성된다.
  * lifecycle은 onStop() > onDestroy() (Activity 파괴) > onCreate() (Activity 재 생성) > ...

2. 
Given; Manifest에 `android:configChanges` 이 추가된 상태
When; Configuration Change 가 발생한 경우
Then; Activity가 재생성되지 않는다. 
  * lifecycle이 다시 시작되지 않고, onConfigurationChanged() 만 호출.

3. RecyclerView

RecycleView에서 Configuration Change 가 발생하는 경우에 Scroll Position을 유지하고 싶은 경우 position 이나 offset을 저장하는 방법이 있겠지만, 별개로 RecyclerView의 stateRestorationPolicy 옵션을 통해 설정할 수 있다.

recyclerView.adapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.ALLOW

위와같이 설정할 수 있으며, 기본적으로 stateRestorationPolicy은 ALLOW가 default로 설정되어 있다.

각 옵션에 대해 설명하자면,
1. ALLOW - 항상 어댑터의 상태를 저장한다.
2. PREVENT - 어댑터의 상태를 저장하지 않는다.
3. PREVENT_WHEN_EMPTY - 어댑터로부터 설정되는 리스트가 1개 이상일 때 상태를 저장한다.


또는 LayoutManager 자체를 저장할 수도 있다.

//save
val recyclerViewState = recyclerView.layoutManager.onSaveInstanceState()

//restore
recyclerView.layoutManager.onRestoreInstanceState(recyclerViewState)

4. 해상도 별 dimens 지정

해상도 별로 View의 설정 값(width, height, margin etc,..)을 다르게 적용하고 싶은 경우 dimens.xml 을 이용하면 된다.

다만 해상도 별 절대값으로 대응하고자 할 때는 간단하게 적용할 수 있는 방법이지만, 디자인측에서 상대값으로 대응하고자 하는 경우에는 Constraint Layout 을 이용하거나, 별도의 device screen에 비례하는 size를 programmatically 계산해서 적용할 수 있겠다.


5. 디바이스 사이즈 별 layout 지정

아래는 일반적인 디바이스 화면 크기를 나누는 기준이다.

  1. 320dp: 일반적인 전화 화면(240x320 ldpi, 320x480 mdpi, 480x800 hdpi 등).
  2. 480dp: 대형 스마트폰 화면, 최대 5인치까지(480x800 mdpi).
  3. 600dp: 7” 태블릿(600x1024 mdpi).
  4. 720dp: 10” 태블릿(720x1280 mdpi, 800x1280 mdpi 등).

이를 바탕으로 layout-sw600dp 폴더를 생성하는 경우 아래와 같이 경로를 설정할 수 있는데,

res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)
  1. 디바이스의 너비가 600dp 보다 작은 경우에는 res/layout 경로에 있는 main_activity.xml 을 사용
  2. 디바이스의 너비가 600dp 보다 큰 경우에는 res/layout-sw600dp 경로에 있는 main_activity.xml 사용

여기서 sw600dp 의 "sw" 란, smallestWidth 의 줄임말로 최소 지원 디바이스 크기를 정할 때 사용되는 suffix로 사용된다. 결국 layout-sw600dp의 의미는 "디바이스 가로 크기가 600dp를 넘기는 경우 layout-sw600dp 경로에 있는 layout resource 를 사용한다." 이다.
이런방법으로 layout 폴더 생성 시 규칙을 정하면 내가 원하는 범위에 해당하는 레이아웃이 설정된다.

이 외에도 폴더 이름을 설정할 때 사용할 수 있는 여러가지 한정자가 있으므로 참고하면 좋다.




profile
android developer @bucketplace

0개의 댓글