일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 끝말잇기
- 베드트레이
- 지지않는다는말
- 테트리스
- 한달어스
- 재택근무
- 캐치마인드
- 프래그먼트
- 어떻게 나답게 살 것인가
- 북한살둘레길
- 아비투스
- 베드테이블
- 1일1커밋
- 커스텀린트
- 목적중심리더십
- 한달독서
- 브런치작가되기
- 소프시스 밤부 좌식 엑슬 테이블
- 면접
- 소프시스
- 슬기로운 온라인 게임
- 리얼하다
- 자취필수템
- 좌식테이블
- 한단어의힘
- 목적 중심 리더십
- 함수형 프로그래밍
- 한달브런치북만들기
- T자형인재
- 안드로이드
- Today
- Total
정상에서 IT를 외치다
[Android, MVP] MVP 기본 예제 본문
안녕하세요. 블랙진입니다.
안드로이드 MVP 를 활용한 토이 프로젝트 리뷰 포스팅입니다. 총 3단계에 걸쳐서 앱을 리뷰하겠습니다.
1. MVP 기본 예제
2. Room 사용하기
3. Dagger 사용하기
<작업>
1. http://api.randomuser.me/?results=10 API를 통해 랜덤한 깃허브 유저 데이터를 받아옵니다.
2. 받아온 데이터를 Recycler View 에 보여줍니다.
3. API 데이터 외 Like 값을 넣을 수 있는 로컬 변수를 추가해 주었습니다.
4. 유저의 상세화면에서 Like 버튼을 누른 갯수 만큼 유저 리스트에서 유저의 Like 값이 증가됩니다.
위 작업물은 링크에서 다운받으실 수 있습니다.
그럼 <작업> 에서 보이는 앱을 MVP 패턴으로 바꾼 코드에 대해 리뷰를 시작하겠습니다.
MVP 변환 작업이 끝난 결과물을 보고 싶은신 분인 MyAndroidArchitecture를 확인해 주세요.
1. MVP?
MVP는 model, view, presenter 의 아키텍처로 이루어진 구조입니다.
View 에서는 오로지 사용자가 보고 있는 화면의 상태변화만을 보여줍니다. 사용자가 화면을 클릭 했을 때의 이벤트는 Presenter 로 전달됩니다. Presenter 에서는 뷰에서 받아온 액션을 처리하는 비즈니스 로직이 들어갑니다.
2. BaseContract
View 와 Presenter 는 1:1로 연결되기 때문에 뷰의 연결과 해제를 위한 함수를 정해줍니다.
public class BaseContract {
//View 와 Presenter 는 1:1로 연결되기 때문에 뷰의 연결과 해제를 위한 함수를 정해줍니다.
public interface Presenter<T> {
void setView(T view);
void releaseView();
}
//View 의 공용 함수가 필요한 경우 정해줍니다.
public interface View {
}
}
3. Main
Main은 랜덤유저 API를 통신해 화면에 유저 리스트로 보여줍니다.
MainContract
public interface MainContract {
interface View extends BaseContract.View {
void showProgress();
void hideProgress();
void showToast(String message);
// 아이템을 어댑터에 연결해 줍니다.
void setItems(ArrayList<User> items);
// 단일 아이템에 변경되었음을 알려줍니다.
void updateView(User user);
}
interface Presenter extends BaseContract.Presenter<View> {
@Override
void setView(View view);
@Override
void releaseView();
// API 통신을 통해 데이터를 받아옵니다.
void loadData();
// RxEventBus 를 연결하여 Like 값을 동기화 해줍니다.
void setRxEvent();
}
}
MainActivity 의 Contract 입니다. View 와 Presenter 에 관한 내용을 한눈에 볼수 있습니다.
MainAcitvity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("RANDOM USER");
// recycler view 초기화
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
adapter.setClickListener(this);
// presenter 와 연결
presenter.setView(this);
// 랜덤 유저 데이터를 받아옵니다.
presenter.loadData();
// RxEventBus 를 연결합니다.
presenter.setRxEvent();
}
@Override
protected void onDestroy() {
super.onDestroy();
// presenter 와의 연결을 해제합니다.
presenter.releaseView();
}
@Override
public void onClick(User user) {
// 어탭터 리스터로 아이템 클릭 시 상세 유저 화면으로 넘어갑니다.
// intent 통해 user 데이터를 넘겨줍니다.
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(DetailActivity.KEY_USER, user);
startActivity(intent);
}
@Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
@Override
// 아이템을 어댑터에 연결해 줍니다.
public void setItems(ArrayList<User> items) {
adapter.setItems(items);
}
@Override
// 단일 아이템에 변경되었음을 알려줍니다.
public void updateView(User user) {
adapter.updateView(user);
}
데이터를 받아오는 부분과 Like 클릭 시 이뤄지는 비즈니스 로직은 모두 Presenter 이뤄지며 Activity 에서는 오로지 뷰의 변화만을 코드로 보여주고 있습니다.
MainPresenter
public MainPresenter() {
this.api = GithubApiProvider.provideGithubApi();
this.disposable = new CompositeDisposable();
}
생성자를 통해 통신을 위한 변수를 초기화 해줍니다.
@Override
public void loadData() {
disposable.add(api.getUserList(Constant.RANDOM_USER_URL)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(__ -> {
view.showProgress();
})
.doOnTerminate(() -> {
view.hideProgress();
})
.subscribe(userResponse -> {
view.setItems((ArrayList<User>)userResponse.userList);
}, error -> {
view.showToast(error.getMessage());
})
);
}
RxJava 를 사용해 Api 통신을 합니다.
@Override
public void setRxEvent() {
disposable.add(
RxEvent.getInstance()
.getObservable()
.subscribe(
object -> {
if(object instanceof User) {
view.updateView((User) object);
}
},
// 아래 코드는 생략 가능 합니다.
error -> {
Log.d("MyTag","onError");
},
() -> {
Log.d("MyTag","onCompleted");
}
)
);
}
RxJava 를 사용해 유저의 단일 아이템을 업데이트 해줍니다.
@Override
public void releaseView() {
disposable.clear();
}
마지막으로 disposable 변수를 사용했기 때문에 presenter 가 해제가 되면 disposable 변수를 clear 해줍니다.
4. Detail
Detail른 유저 상세정보를 보여주고 Like 버튼을 클릭하여 갯수를 늘릴 수 있습니다.
DetailContract
public interface DetailContract {
interface View extends BaseContract.View {
void setText(String text);
}
interface Presenter extends BaseContract.Presenter<View> {
@Override
void setView(DetailContract.View view);
@Override
void releaseView();
void clickEvent(User user);
}
}
View 에서는 like 갯수의 변화를 보여줄 setText 함수와
Presenter 에서는 버튼을 클릭했을 때의 비즈니스 로직을 처리합니다.
DetailActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
// presenter 와 연결
presenter = new DetailPresenter();
presenter.setView(this);
// MainActivity 로부터 User 객체를 받아옵니다.
getUserFromIntent();
}
private void getUserFromIntent(){
user = (User) getIntent().getSerializableExtra(KEY_USER);
setTitle(user.getFullName());
// 받아온 User 객체로 부터 View 를 초기화 해줍니다.
initView(user);
}
MainActivity 와 달리 preenter.relaseView() 함수를 설정해 주지 않았습니다. 여기서는 따로 Presnter 을 해제해줄 필요가 없습니다.
DetailPresenter
@Override
public void clickEvent(User user) {
// Like 클릭시 발생하는 비즈니스 로직입니다.
// User 객체의 LikeCnt 값을 늘려 줍니다.
user.likeCnt++;
// view 상태에 변화를 줍니다.
view.setText(user.getLikeCnt());
// RxEventBus 를 호출하여 MainActivity 에 변화가 생겼음을 알려줍니다.
RxEvent.getInstance().sendEvent(user);
}
이렇게 MVP 패턴을 활용한 간단한 깃허브 예제를 작성해 보았습니다. 여기에 Room 을 활용하여 클릭한 유저들을 저장해보고 Dagger 를 사용하여 외부에서 객체를 주입할 수 있는 방법에 대해 차례로 포스팅을 진행해보겠습니다.
위 예제 코드는 링크 에서 확인하실 수 있습니다.
1. MVP 기본 예제
2. Room 사용하기
3. Dagger 사용하기
'안드로이드' 카테고리의 다른 글
[Android, MVP, Dagger] MVP 기본 예제 - Dagger 사용하기 (0) | 2019.02.08 |
---|---|
[Android, MVP, Room] MVP 기본 예제 - Room 활용 (0) | 2019.02.07 |
[Android, Canvas, PorterDiff] PorterDiff.Mode 사용해 모서리가 둥근 이미지 만들기 (2) | 2019.01.21 |
[Android, Canvas, Paint] 안드로이드 캔버스 기본 예제 (4) | 2019.01.21 |
[리액티브 프로그래밍] 스케줄러 개념 배우기 (0) | 2019.01.03 |