오늘도 더 나은 코드를 작성하였습니까?

생명주기 인식 구성요소의 권장사항 및 예시 본문

Android Jetpack Architecture/LifeCycle

생명주기 인식 구성요소의 권장사항 및 예시

hik14 2020. 8. 13. 17:30

권장사항 

UI 컨트롤러(활동과 프래그먼트)를 가능한 한 가볍게 유지하세요. 이러한 컨트롤러는 자체 데이터를 확보하려고 해서는 안 됩니다. 대신 ViewModel을 사용하여 데이터를 확보하고 LiveData 객체를 관찰하여 변경사항을 다시 뷰에 반영한다(DataBinding 을 이용한다)

데이터 기반 UI를 작성해 보세요. 여기서 데이터 변경에 따라 뷰를 업데이트하거나 사용자 작업을 다시 ViewModel에 알리는 것은 UI 컨트롤러의 책임입니다.

 

ViewModel 클래스에 데이터 로직을 넣으세요. ViewModel은 UI 컨트롤러와 나머지 앱 간의 커넥터 역할을 해야 합니다. 하지만 데이터를 가져오는 것(예: 네트워크에서 데이터 가져오기)은 ViewModel의 책임이 아닙니다. 대신 ViewModel은 적절한 구성요소를 호출하여 데이터를 가져온 후 결과를 다시 UI 컨트롤러에 제공해야 합니다.

 

데이터 결합을 사용하여 뷰와 UI 컨트롤러 간의 인터페이스를 깔끔하게 유지하세요. 이렇게 하면 뷰를 더욱 선언적으로 만들고, Activity와 Fragment에서 작성해야 하는 업데이트 코드를 최소화할 수 있습니다.

이 작업을 자바 프로그래밍 언어로 진행하려면 Butter Knife와 같은 라이브러리를 사용하여 상용구 코드를 피하고 더 나은 추상화를 구현하세요.

 

UI가 복잡하다면 UI 수정을 처리할 presenter 클래스를 만드는 것이 좋습니다. 힘든 작업이지만, 이렇게 하면 UI 구성요소를 더 쉽게 테스트할 수 있습니다. (MVP 패턴에서 Presenter를 생성하여 비즈니스 로직을 Presenter에서 관리)

 

ViewModel에서 View 또는 Activity 컨텍스트를 참조하지 마세요. ViewModel이 활동보다 오래 지속되면(구성이 변경되는 경우) Activity가 누출되고 가비지 컬렉터가 활동을 제대로 처리하지 못합니다.

 

Kotlin 코루틴을 사용하여 장기 실행 작업 및 비동기적으로 실행될 수 있는 기타 작업을 관리하세요.

 

수명 주기 인식 구성요소의 사용 사례

위치기반 서비스를 만들때.

대략적인 위치와 세분화된 위치 업데이트 간 전환. 수명 주기 인식 구성요소를 사용하면 위치 앱이 공개 상태인 동안 세분화된 위치 업데이트를 사용하고 앱이 백그라운드에 있을 때 대략적인 위치 업데이트로 전환할 수 있습니다. 수명 주기 인식 구성요소인 LiveData를 사용하면 사용자가 위치를 변경할 때 앱에서 자동으로 UI를 업데이트할 수 있습니다.

 

동영상플레이가 필요한 앱을 만들때.

동영상 버퍼링 중지와 시작. 수명 주기 인식 구성요소를 사용하면 동영상 버퍼링을 최대한 빨리 시작하지만, 앱이 완전히 시작될 때까지 재생을 연기합니다. 또한 수명 주기 인식 구성요소를 사용하여 앱이 제거될 때 버퍼링을 종료할 수 있습니다.

 

네트워크를 통해 필요한 데이터를 요청할때

네트워크 연결 시작과 중지. 수명 주기 인식 구성요소를 사용하면 앱이 포그라운드에 있는 동안 네트워크 데이터를 실시간으로 업데이트(스트리밍)할 수 있으며 앱이 백그라운드로 전환될 때 실시간 업데이트를 자동으로 일시중지할 수도 있습니다.

 

애니메이션관련 리소스의 할당과 해제

애니메이션 드로어블 일시중지와 재개. 수명 주기 인식 구성요소를 사용하면 앱이 백그라운드에 있는 동안 애니메이션 드로어블 일시중지를 처리하고 앱이 포그라운드로 전환한 후 드로어블을 재개할 수 있습니다.

 

중지 이벤트 처리

Lifecycle AppCompatActivity 또는 Fragment에 속하면 Lifecycle의 상태가 CREATED로 변경고 AppCompatActivity 또는 Fragment onSaveInstanceState()가 호출되면 ON_STOP 이벤트가 전달됩니다.

 

 

onSaveInstanceState()를 통해 Fragment 또는 AppCompatActivity의 상태를 저장하면 ON_START가 호출될 때까지 UI는 변경할 수 없는 것으로 간주됩니다. 상태를 저장한 후 UI를 수정하려고 하면 애플리케이션의 탐색 상태에 불일치가 나타날 수 있습니다. 따라서 상태가 저장된 후 앱에서 FragmentTransaction을 실행하면 FragmentManager가 예외를 발생시킵니다. 자세한 내용은 commit()을 참조하세요.

 

 

LiveData는 관찰자의 관련 Lifecycle이 적어도 STARTED 상태가 아니라면 관찰자를 호출하지 않게 하여 이러한 에지 케이스(edge case)를 처음부터 방지합니다. 하지만 이면에서는 관찰자 호출을 결정하기 전에 isAtLeast()를 호출합니다.

 

아쉽게도 AppCompatActivity onStop() 메서드는 onSaveInstanceState() 이후에 호출되어 UI 상태 변경이 허용되지 않지만 Lifecycle이 아직 CREATED 상태로 전환되지 않는다는 차이가 생깁니다.

 

이 문제를 방지하기 위해 beta2 버전 이하의 Lifecycle 클래스는 이벤트를 전달하지 않아도 상태를 CREATED로 표시하여, 시스템에서 onStop()을 호출할 때까지 이벤트가 전달되지 않았더라도 현재 상태를 확인하는 모든 코드가 실제 값을 받도록 합니다.

 

하지만 이 솔루션에는 다음 두 가지 중대한 문제가 있습니다.

 

  • API 수준 23 이하에서 Android 시스템은 다른 활동으로 인해 활동이 일부 가려진 경우에도 활동의 상태를 실제로 저장합니다. 즉, Android 시스템은 onSaveInstanceState()를 호출하지만 반드시 onStop()을 호출할 필요는 없습니다. 이로 인해 UI 상태를 수정할 수 없더라도 관찰자는 수명 주기가 계속 활성 상태라고 생각하는 긴 간격이 발생할 수 있습니다.
  • LiveData 클래스에 유사한 동작을 노출하려는 모든 클래스는 Lifecycle 버전 beta 2 이하에서 제공되는 해결 방법을 구현해야 합니다.