정상에서 IT를 외치다

[Android Architecture Component] 라이프 사이클 본문

안드로이드

[Android Architecture Component] 라이프 사이클

Black-Jin 2018. 11. 27. 16:06
반응형


안녕하세요. 블랙진 입니다.


2017 구글 IO 에서 공개 했던 안드로이드 아키텍처 컴포넌트에 대해 포스팅 하겠습니다.


안드로이드 아키텍처 컴포넌트(Android Architecture Components)?


구글에서 가이드를 제시한 애플리케이션의 구조(아키텍처)입니다. 지금까지 MVC, MVP, MVVM 과 같은 구조가 나왔지만 구글에서 애플리케이션에 최적화된 구조인 AAC를 공식적으로 제시한 거죠! AAC는 액티비티와 프래그먼트의 생명주기, 화면 크기, 하드웨어 환경 등 여러 요소에 대응할 수 있는 구조입니다. 이를 구현 하는 방법에 대해 하나씩 포스팅을 진행해 보겠습니다.



먼저 AAC 에 중 무엇이 있는지 알아 보겠습니다.


1. LifeCycle

- 엑티비티나 프래그먼트의 생명주기를 감지하고 이에 따른 작업을 수행할 수 있게 도와줍니다.


2, LiveData

- 지속적으로 변할 수 있는 값을 생명주기에 맞게 전달할 수 있도록 해줍니다.


3. ViewModel

- 생명주기 변화에 맞서 UI 표시에 필요한 데이터를 관리할 수 있도록 해줍니다.


4. Room

- SQLite 데이터베이스와 관련된 작업을 간편하게 사용할 수 있도록 해줍니다.


위 4가지 사항을 순서대로 프로젝트에 적용해 보도록 하겠습니다. 먼저 예제로 사용할 프로젝트는 입니다. 깃 허브 유저 정보를 받아서 화면에 보여줍니다. 해당 아이템을 누르면 상세 정보를 볼 수 있고 like 버튼을 눌러 좋아요를 표시할 수 있습니다.(좋아요는 서버 통신이 아닙니다.)



LifeCycle - 생명주기에 맞는 동작 수행하기


LifeCycle 은 Event, State 그리고 LifeCycleObserver 로 구성되어 있습니다.

출저(구글 문서)


Event

- 액티비티나 프래그먼트에서 발생하는 생명주기 이벤트에 대응


ON_CREATE, ON_DESTROY, ON_PAUSE, ON_RESUME, ON_START, ON_STOP


State

- 액티비티나 프래그먼트의 현재 상태에 대응


INITIALIZED, CREATED, DESTROYED, STARTED, RESUMED



LifecycleObserver

/**
* Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on
* {@link OnLifecycleEvent} annotated methods.
* <p>
* @see Lifecycle Lifecycle - for samples and usage patterns.
*/
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {

}

- 인터페이스로 구성되어 있으면 어노테이션 @onLifeCycleEvent 을 사용하여 생명주기에 대응하는 컴포넌트를 관리할 수 있습니다.



예제


사용하는 예제 에서는 CompositeDisposable() 을 사용해 통신 및 RxEvent 를 처리하고 onDestroy 함수에서 자원을 해체해 주고 있습니다. 이를 LifeCycle 를 사용해 처리하도록 해보겠습니다.


1. AutoClearedDispossable 클래스 생성

public class AutoClearedDisposable implements LifecycleObserver {

private AppCompatActivity lifecycleOwner;

//alwaysClearOnStop 변수는 onStop 에서 자원을 해체해 줄지 말지를 정합니다.
private Boolean alwaysClearOnStop;

//compositeDisposable 생성
private CompositeDisposable compositeDisposable;

public AutoClearedDisposable(AppCompatActivity lifecycleOwner) {
this.lifecycleOwner = lifecycleOwner;

this.alwaysClearOnStop = true;
this.compositeDisposable = new CompositeDisposable();
}

public AutoClearedDisposable(AppCompatActivity lifecycleOwner, Boolean alwaysClearOnStop) {
this.lifecycleOwner = lifecycleOwner;

this.alwaysClearOnStop = alwaysClearOnStop;
this.compositeDisposable = new CompositeDisposable();
}

public void add(Disposable disposable) {
//lifecycleOwner 의 현재 상태가 INITIALIZED 상태 이후 인지를 확인합니다.
Boolean isAtLeast = lifecycleOwner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.INITIALIZED);
Log.d("blackjin","isAtLeast : " + isAtLeast);

//초기화가 이루어진 상태 이후면 disposable 객체를 추가해 줍니다.
if(isAtLeast)
compositeDisposable.add(disposable);
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void pause() {
Log.d("blackjin","ON_PAUSE");
}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void cleanUp() {
Log.d("blackjin","ON_STOP");
if(!alwaysClearOnStop) return;

Log.d("blackjin","compositeDisposable clear ");
// 디스포저블을 해제합니다.
compositeDisposable.clear();
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void detachSelf() {
Log.d("blackjin","ON_DESTROY");
// 디스포저블을 해제합니다.
compositeDisposable.clear();

// 더 이상 엑티비티의 생명주기 이벤트를 받지 않도록 lifecycleOwner 를 옵서버에서 제거합니다.
lifecycleOwner.getLifecycle().removeObserver(this);
}
}


2. MainActivity 에 연결

public class MainActivity extends BaseActivity implements MainAdapter.OnItemClickListener {

//private CompositeDisposable disposable = new CompositeDisposable();

private AutoClearedDisposable disposables = new AutoClearedDisposable(this);
private AutoClearedDisposable viewDisposables = new AutoClearedDisposable(this, false);

private GithubApi api = GithubApiProvider.provideGithubApi();

private MainAdapter adapter = new MainAdapter();

@BindView(R.id.recycler_view)
RecyclerView recyclerView;

@BindView(R.id.progress_view)
ProgressBar progressBar;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("RANDOM USER");

recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
adapter.setClickListener(this);

getLifecycle().addObserver(disposables);
getLifecycle().addObserver(viewDisposables);

disposables.add(api.getUserList(Constant.RANDOM_USER_URL)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(__ -> {
progressBar.setVisibility(View.VISIBLE);
})
.doOnTerminate(() -> {
progressBar.setVisibility(View.GONE);
})
.subscribe(userResponse -> {
//아이템 로드
adapter.setItems((ArrayList<User>)userResponse.userList);
}, error -> {
showToast(error.getMessage());
})
);

viewDisposables.add(
RxEvent.getInstance()
.getObservable()
.subscribe(
object -> {
if(object instanceof User) {
adapter.updateView((User) object);
}
},
error -> {
Log.d("MyTag","onError");
},
() -> {
Log.d("MyTag","onCompleted");
}
)
);

}

@Override
protected void onDestroy() {
super.onDestroy();
//기존 사용했던 disposable 객체를 해제해 주지 않아도 됩니다.
//disposables.clear
}

@Override
public void onClick(User user) {
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(DetailActivity.KEY_USER, user);
startActivity(intent);
}

}

위 함수 에서 onCreate 부분에서 두 부분만 보면 됩니다. 

getLifecycle().addObserver(disposables);
getLifecycle().addObserver(viewDisposables);

저는 onStop 에서 자원을 해제할 수 있는 disposables 와 onDestroy 에서만 자원을 해제할 수 있는 viewDisposables 를 생성했습니다.


LifecycleOwner(여기선 MainActivity)의 getLifeCycle 에 addObserver 를 사용해 추가해주면 해당 Activity 에서 생명주기를 처리하지 않아도 AutoClearedDisposable 에서 생명주기를 통합적으로 관리할 수 있게 됩니다.


<참고자료>

AAC Code Lab


반응형
Comments