-
RecyclerView in MVP — Passive view’s approach -2디자인패턴 2017. 7. 26. 02:13반응형
RecyclerView를 사용할 때, 드는 생각은 Data를 어떻게 관리할 것인지이다. 항상 고민되는 문제이다. Passive View 를 만들자는 관점에서 RecyclerView에서 사용하는 Data는 어떻게 관리되어야 할까?
대부분의 사람들은 Adapter에 Collection(List)를 생성하는 경향이 있다. Adapter에 Collection(List)를 직접 참조하는 건 정말 별로다!! 우리는 일반적으로 MVP 패턴에서 Presenter에 이 데이터를 갖게 한다. 그래서 Adapter와 Presenter에 Data를 가지고 있기 때문에 이를 sync하기 위해서는 두 배로 시간이 든다.
첫 번째로, 데이터를 Adapter에서 removing, adding, or updating하는 것은 Passive view의 원칙에 벗어난다. 그리고 MVP 패턴에서는 이 모든 Presentation logic은 Presenter에 속해야한다.
해결방법은 아래와 같다. Adapter가 Data를 사용해야할 때, Presenter에 알려주는(notify) 방법을 사용하면 된다.
public class RepositoriesRecyclerAdapter extends RecyclerView.Adapter<ReposRecyclerAdapter.RepoViewHolder> { private final RepositoriesListPresenter presenter; public ReposRecyclerAdapter(RepositoriesListPresenter repositoriesPresenter) { this.presenter = repositoriesPresenter; } @Override public RepositoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new RepositoryViewHolder(LayoutInflater.from(parent.getContext()) .inflate(R.layout.cell_repo_view, parent, false)); } @Override public void onBindViewHolder(RepositoryViewHolder holder, int position) { presenter.onBindRepositoryRowViewAtPosition(position, holder); } @Override public int getItemCount() { return presenter.getRepositoriesRowsCount(); } }
아마 눈치 챘을 수도 있는데, holder를 Presenter에 참초하도록 하고 있다.우리는 이전 post에서 읽은 적이 있다. Presenter는 UI Test를 피하기 위해서 Android Framework와의 의존성을 가지면 안 된다는 것을!!걱정 하지 않아도 된다! RepositoryViewHolder의 구현은 아래와 같다.public class RepositoryViewHolder extends RecyclerView.ViewHolder implements RepositoryRowView { TextView titleTextView; TextView starsCountTextView; public RepositoryViewHolder(View itemView) { super(itemView); titleTextView = itemView.findViewById(R.id.repoTitleText); starsCountTextView = itemView.findViewById(R.id.repoStarsCountText); } @Override public void setTitle(String title) { titleTextView.setText(title); } @Override public void setStarCount(int starCount) { starsCountTextView.setText(String.format("%s ★", starCount)); } }
holder에서 보면 알 수 있듯이, RepositoryViewHolder는 RepositoryRowView를 상속하고 있다. 아래는 MVP 패턴에서 View에 해당하는 interface라고 볼 수 있다.
interface RepositoryRowView { void setTitle(String title); void setStarCount(int starCount); }
Presenter에서는 View의 구현체가 아닌 interface만 가지고 있으면 된다.
public class RepositoriesListPresenter { private final List<Repository> repositories; ... public void onBindRepositoryRowViewAtPosition(int position, RepositoryRowView rowView) { Repository repo = repositories.get(position); rowView.setStarCount(repo.getStarsCount()); rowView.setTitle(repo.getTitle()); } public int getRepositoriesRowsCount() { return repositories.size(); } ... }
이 방법 대로라면, RecyclerView의 각 row가 data를 들고 있지 않아도 되며 MVP의 약속인 Passive View 를 지킬 수 있다.
Adapter는 특정 row를 그릴 이벤트를 전달하고, Data를 수정하거나 View에 알려줘야할 일이 생기면 Presenter에 요청하면 된다.
반응형'디자인패턴' 카테고리의 다른 글
[Android] MVC vs MVP vs MVVM (0) 2017.08.01 RecyclerView in MVP - Passive view's approach -1 (0) 2017.07.26