본문 바로가기
개발/안드로이드

Android Architecture Components - Handling Lifecycles

by darksilber 2019. 5. 28.
반응형

출처: https://tourspace.tistory.com/24?category=788397 [투덜이의 리얼 블로그]

 

Android Architecutre component에서는 lifecycle을 다루기 위해서 새로운 방법을 제시합니다.

Activity와 Fragment의 lifecycle에 따른 동작을 정의할 수 있는 class와 interface를 android.arch.lifecycle package를 제공합니다.

위치를 얻어오는 코드를 작성하는 예제를 통해서 어떻게 life cycle을 다루는지 알아보겠습니다.

class MyLocationListener { public MyLocationListener(Context context, Callback callback) { // ... } void start() { // connect to system location service } void stop() { // disconnect from system location service } } class MyActivity extends AppCompatActivity { private MyLocationListener myLocationListener; public void onCreate(...) { myLocationListener = new MyLocationListener(this, (location) -> { // update UI }); } public void onStart() { super.onStart(); myLocationListener.start(); } public void onStop() { super.onStop(); myLocationListener.stop(); } }

위 샘플은 심플해 보이지만 실제 구현시 이런식의 호출이 들어나면서 onStart()와 onStop()이 매우 커지게 됩니다.

또한 단순히 onStart()에서 시작하기엔 쉽지도 않지요.

예를들어 activity가 종료된 후에 location.start()가 불리게 되면 location.stop()이 불리지 않으므로 연결이 끊어지지 않을수도 있습니다.

 

LifeCycle

Lifecycle 클래스는 Activity나 Fragment의 component의 lifecycle 상태를 가지며, 다른 object가 이 상태를 observing할수 있도록 합니다.

내부에 두가지의 enum을 갖는데 아래와 같습니다.

 

Lifecycle.Event

  • ON_ANY
  • ON_CREATE
  • ON_DESTROY
  • ON_PAUSE
  • ON_RESUME
  • ON_START
  • ON_STOP

Lifecycle.State

 

  • CREATED: onCreate() 이후나 onStop() 직전에 바뀜
  • DESTROYED : onDestory()가 불리기 직전에 바뀜
  • INITIALIZED: onCreate()가 불리기 직전에 바뀜
  • RESUMED: onResume()이 불린 이후에 바뀜
  • STARTED: onStart() 이후나, onPause() 직전에 바뀜

 

 

 

 

아래와 같이 observer class를 등록하면 lifecycle에 따라 해당 동작을 확인할 수 있습니다.

public class MyObserver implements LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void onResume() { } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void onPause() { } } aLifecycleOwner.getLifecycle().addObserver(new MyObserver());

 

LifeCycleOwner

LifecycleOwner interface는 단일 method를 갖습니다. (getLifecycle())

이 클래스는 각각의 activity나 fragment의 lifecycle의 ownership을 가지며, 이를 구현하여 각 component에 끼워 넣을 수 있도록 도와줍니다.

alpha 버전에서 LifecycleActivity LifecycleFragment 를 사용해야 하지만 추구 안정버전이 release되면, Fragment 및 AppCompatActivity에 구현사항이 들어가므로 두개의 class는 추후 deprecate 될 예정이라고 하네요.

class MyActivity extends LifecycleActivity { private MyLocationListener myLocationListener; public void onCreate(...) { myLocationListener = new MyLocationListener(this, getLifecycle(), location -> { // update UI }); Util.checkUserStatus(result -> { if (result) { myLocationListener.enable(); } }); } }

listener의 생성자로 getLifecycle()을 넘겨줍니다. 또한 listener가 동작 가능한 상태인지도 알려줘야 하죠.

예를 들어 callback 동작에서 fragment transaction을 하도록 했을때, 만약 activity가 종료된 상태라면, crash가 발생될 수 있기 때문입니다.

class MyLocationListener implements LifecycleObserver { private boolean enabled = false; public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) { ... } @OnLifecycleEvent(Lifecycle.Event.ON_START) void start() { if (enabled) { // connect } } public void enable() { enabled = true; if (lifecycle.getState().isAtLeast(STARTED)) { // connect if not connected } } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) void stop() { // disconnect if connected } }

 

따라서 Lifecycle class는 다른 object들이 현재 상태를 쉽게 읽어갈 수 있도록 해줍니다.

생성자에서 전달받은 Lifecycle 객체에서 getCurrentState()를 통해 LifeCycle.State 를 얻고, isAtLeast()를 통해 상태 확인후 작업을 진행할 수 있습니다.

중요한점은 observer가 lifecycle을 확인할 수 있다는 것인데요!! 그렇게 때문에 activity나 fragment가 호출하지 않아도 스스로 initialize나, cleanup 할수 있습니다.

LifeCycle 을 이용해서 동작하는 클래스들을 lifecycle-aware components라고 합니다.

만약 라이브러리에서 Android lifecycle을 이용하는 class를 제공한다면, lifecycle을 제공하는 형태로 구성하여 이를 사용하는 client에서 사용성이 더 좋도록 해야 합니다.

LiveData는 ifecycle-aware components 중에 하나이며, ViewModel과 사용되면서 UI를 표시를 훨씬 더 쉽게 해줍니다.

 

Best Practice

  1. Activity나 Fragment같은 UI controller를 최대한 가볍게 유지하라. UI controller가 데이터를 수집하지 않도록 하고 이를 ViewModel에 위임하라.
  2. LiveData를 observing하여, View에 변경사항을 반영하도록 구성한다.
  3. ViewModel은 UI controller와 나머지 앱 구성요소를 연결하는 역할을 하도록 한다. ViewModel에서 data를 직접 fetch하는것이 아니라, fetching 역할을 하는 적절한 component와 연결하는 작업을 해야한다.
  4. Data binding을 사용하면 view와 UI component간 관계를 좀더 clean하게 해줄 수 있다.
  5. UI가 복잡하다면 Presenter를 이용하여 UI 변경을 관리하라.
  6. ViewModel에서 view나 Activity context를 참조하면 안된다. ViewModel은 activity와 생명주기가 다른기 때문에 leak을 발생시킬 수 있다.

 

Custom activity나 fragment에서 LifecycleOwner의 구현

public class MyFragment extends Fragment implements LifecycleRegistryOwner { LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this); @Override public LifecycleRegistry getLifecycle() { return lifecycleRegistry; } }



반응형

댓글