일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 북한살둘레길
- 좌식테이블
- 커스텀린트
- 베드테이블
- 소프시스 밤부 좌식 엑슬 테이블
- 어떻게 나답게 살 것인가
- 함수형 프로그래밍
- 테트리스
- 리얼하다
- 한달브런치북만들기
- 소프시스
- 프래그먼트
- 한단어의힘
- 베드트레이
- 브런치작가되기
- 1일1커밋
- 지지않는다는말
- 목적 중심 리더십
- 한달어스
- 한달독서
- 재택근무
- 끝말잇기
- T자형인재
- 목적중심리더십
- 아비투스
- 자취필수템
- 면접
- 캐치마인드
- 안드로이드
- 슬기로운 온라인 게임
- Today
- Total
정상에서 IT를 외치다
[Android Architecture Component] 라이프 사이클 본문
안녕하세요. 블랙진 입니다.
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 에서 생명주기를 통합적으로 관리할 수 있게 됩니다.
<참고자료>
'안드로이드' 카테고리의 다른 글
[번역] MVVM 디자인 패턴의 기본 이해 (0) | 2018.12.13 |
---|---|
[Android, Koin] 코인을 사용한 의존성 주입 기본 예제 (4) | 2018.12.05 |
[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (크롭 기능 추가) (10) | 2018.10.23 |
[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (카메라 회전각도 적용) (6) | 2018.10.23 |
[Android,GetImage] 카메라와 갤러리에서 이미지 가져오기 (Nougat 대응) (6) | 2018.10.23 |