ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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
Designed by Tistory.