마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리사이클러뷰를 구현했는데 데이터 설정시점 질문드려요..

0 추천

부스터코스 프로젝트 진행하며 공부중인 초보자입니다.

앱 구현할때 리스트뷰가 필요한데 스크롤뷰안에 넣으면 아이템이 하나밖에 안보이는 현상이 발생하더라구요.

이것때문에 근본적으로는 해결하지 못하고 그냥 리사이클러뷰로 싹 갈았더니 잘되네요!

근데 별개로 리사이클러뷰의 데이터 설정 시점에 질문좀 드리겠습니다.

아래는 먼저 코드입니다.

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> {
    ArrayList<ListItem> items = new ArrayList<>();

    public void addItem(ListItem item) {
        items.add(item);
    }
    public void setItems(ArrayList<ListItem> items) {
        this.items = items;
    }

    // position번째 아이템 리턴
    public ListItem getItem(int position) {
        return items.get(position);
    }

    public void setItem(int position, ListItem item) {
        items.set(position, item);
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 뷰홀더를 생성시점에 자동호출 메소드
        // 각각의 아이템을 위한 레이아웃을 인플레이션 후 뷰홀더에 넣어서 뷰홀더를 리턴하면 하나의 아이템을 위한 뷰홀더가 만들어져서 리턴됨
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        View itemView = inflater.inflate(R.layout.list_item,parent,false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // 뷰홀더 재사용위한 메소드
        ListItem item = items.get(position);
        holder.setItem(item);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView profile; // 프로필 사진
        TextView name; // 이름(아이디)
        RatingBar score; // 평점
        TextView comment; // 한줄평 내용
        TextView time; // 작성시간

        public ViewHolder(View itemView) {
            super(itemView);

            profile = itemView.findViewById(R.id.profile);
            name = itemView.findViewById(R.id.name);
            comment = itemView.findViewById(R.id.comment);
            score = itemView.findViewById(R.id.score);
            time = itemView.findViewById(R.id.time);
        }

        // onBindViewHolder()에서 재사용되는 뷰홀더 데이터 설정할때 쓰는 것
        public void setItem(ListItem item) {
            name.setText(item.getName());
            comment.setText(item.getComment());
            time.setText(item.getTime());

        }
    }
}

어댑터 클래스입니다.

 

LinearLayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        ItemAdapter adapter = new ItemAdapter();

        adapter.addItem(new ListItem("테스트1","가나다라마바사1","10분전"));
        adapter.addItem(new ListItem("테스트2","가나다라마바사2","13분전"));
        adapter.addItem(new ListItem("테스트3**","가나다라마바사3","14분전"));
        adapter.addItem(new ListItem("테스트4**","가나다라마바사4","15분전"));
        adapter.addItem(new ListItem("테스트5**","가나다라마바사5","15분전"));
        adapter.addItem(new ListItem("테스트6**","가나다라마바사6","15분전"));
        adapter.addItem(new ListItem("테스트7**","가나다라마바사7","15분전"));
        adapter.addItem(new ListItem("테스트8**","가나다라마바사8","15분전"));
        adapter.addItem(new ListItem("테스트9**","가나다라마바사9","15분전"));

        recyclerView.setAdapter(adapter);

메인액티비티에서 리사이클러뷰 생성하고 아이템 생성 및 어댑터 설정입니다.

 

제가 궁금한것은 아이템의 데이터 설정 시점이 언제인가? 입니다.

메인액티비티에서 어댑터의 add()를 이용해서 아이템을 추가합니다. 여기서 파라미터(아이템)는 이제

 보시다시피 ArrayList로 추가가 되겠지요.

 

여기까지는 이해를 했는데, 이 추가된 아이템의 정보(데이터)가 언제 뷰에 셋팅이 되는지 모르겠습니다.

그러니까 각 아이템의 테스트1, 테스트2 테스트3 이러한 데이터가 언제 각 뷰에 설정이 되는지 잘모르겠습니

다.

ViewHolder 클래스 내부에 setItem 이라고 아이템의 데이터를 설정하는게 있긴한데 제가 영상에서 듣기를

onBindViewHolder()에서 재사용되는 뷰홀더 데이터를 설정할때 쓰는것이라고 하더군요.

 

그렇다면 맨~~처음에는 저런 ViewHolder클래스 내부의 setItem()같은 메소드가 정의되어있지도 않는데

어떻게 데이터를 설정하나요? 

혹시 onBindViewHolder에서 실행되는 setItem()이 재사용뿐만아니라

맨처음 시작할때도 설정되는 것인가요?

 

또한

// ArrayList 전체를 설정?
    public void setItems(ArrayList<ListItem> items) {
        this.items = items;
    }

    // position번째 아이템 리턴
    public ListItem getItem(int position) {
        return items.get(position);
    }

    public void setItem(int position, ListItem item) {
        items.set(position, item);
    }

어댑터 클래스에 정의된 이 세가지 메소드는 필요성이 뭔가요? 영상에서 하길래 따라쓰기는 했는데

메소드도 전혀 쓰이는 곳도 없고.. 주석처리하고 실행해봐도 문제없이 실행이 되네요..--

 

질문도 길고 글도 길지만 답변해주시면 감사하겠습니다!

codeslave (3,940 포인트) 님이 2020년 9월 10일 질문

1개의 답변

0 추천
데이터가 어댑터에 설정되는 개념이 아니고
어댑터가 나 몇번째 뷰 띄울건데 거기에 뭐띄울지 말해줘~
이런 방식입니다.
어댑터는 getItemCount를 읽어와서 그 수만큼의 뷰를 띄워주는 역할을 하며 각 위치에 뭘 띄울건지는 개발자가 onBindViewHolder에서 알려주는거죠.
onBindViewHolder는 그 position의 뷰가 보여질때 혹은 보여지는 위치에 가까울때 미리 준비하기 위해 호출됩니다.

마지막 세개의 메소드는 직관적으로 편하게 쓰려고 그냥 선언한것 같네요. 저렇게 쓰면 뷰가 보여지기 이전에만 작동하는 코드입니다.
뷰가 보여지고 있을때도 동작하게 하려면,
setItems에는 notifyDataSetChanged로 나 데이터 바꿨어 다시 띄워줘라는 요청을 해야하고,
setItem 에는 notifyItemchanged(position)으로 나 몇번째뷰 데이터 바꿨어 그 position만 onbindviewholder 호출해서 다시 띄워줘라고 요청해야해요.
물론 딱히 데이터를 바꿀일이 없다면 필요하진 않습니다.
버닝 (4,880 포인트) 님이 2020년 9월 11일 답변
선생님
https://youtu.be/rPW8k3UvD5k?list=PLzkhjlqMgxvBxi3Wyak9NicQI7UwhFU2O
3분 22초부터 onBindViewHolder() 관련 설명부분인데 해당 영상에서는 뷰홀더를 재활용할때 데이터 설정을 해준다고 영상에서 언급하는데요, 제가 이것때문에 질문 드렸는데 답변해주신 내용을보면
 '각 위치에 뭘 띄울건지는 개발자가 onBindViewHolder에서 알려주는거죠.
onBindViewHolder는 그 position의 뷰가 보여질때 혹은 보여지는 위치에 가까울때 미리 준비하기 위해 호출'
이라고 해주셨는데 그럼 영상에서 말한 뷰홀더의 재사용에서만이 아니라
그냥 일반 적으로 데이터를 설정하는게 원래 onBindViewHolder가 사용된다는 말씀인건가요?

제가 이 글을 올린이유가 영상에서는 재사용에서 데이터 설정을 해준다고해서
그럼 재사용 말고 처음 뷰홀더(아이템)의 데이터 설정은 어디서하는거지? 라는게 의문이었어서 질문드린건데 onBindViewHolder()가 재사용이든 그냥 맨처음 뷰홀더든 모든 뷰홀더의 데이터 설정(setItem())을 통해 하는건가요?
생각하신게 맞습니다:)
답변해주셔서 감사합니다!
...