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

array에 데이터 넣고 RecyclerView에 넣는 방법

0 추천
A라는 fragment에 textView에는 배열 index[i]가 차례로 나옵니다. 그중 마음에 드는 것을 클릭 했을 때,

RecyclerView에 들어가게 하고 싶습니다. 한 마디로 즐겨찾기를 구현하려고 합니다.

https://www.youtube.com/watch?v=kNq9w1_nhL4 이 동영상을 참고해서 만들었고 버튼만 fragment에 구현했는데 실행이 되지 않습니다...

구현 방법 아는 분 있나요,,도와주세요 ㅜ
개발개발자 (1,100 포인트) 님이 2020년 12월 30일 질문

2개의 답변

+1 추천
 
채택된 답변

즐겨찾기 데이터를 Adapter에서 관리하지 마시고 외부에서 관리하시는 게 좋은 구조이구요, RecyclerView는 단지 전달 받은 데이터를 화면에 보여주는 역할만 하도록 구성하는 것이 좋습니다.



for (TextView textView :  getTextViews()) {
     textView.setOnClickListener(this);
}

private List<TextView> getTextViews() {
   ...
}

private val FavouriteAdapter favouriteAdapter;

public void onCreate(Bundle saveInstance) {
    super.onCreate(saveInstance);
    setupRecyclerView();
}

private RecyclerView recyclerView;

private void setupRecyclerView() {
   recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

   favouriteAdapter = new FavouriteAdapter();
   recyclerView.setAdapter(favouriteAdapter);
   recyclerView.setLayoutManager(new LinearLayoutManger(getContext());
   recyclerView.setClipToPadding(false);
   recyclerView.hasFixedSize(true);
}


private List<String> favourites = new ArrayList<>();

@Override
public void onClick(View view) {
     TextView selectedTextView = (TextView) view;
     if (selectedTextView == null) throw new IllegalArgumentException("Only textview can be selected");

     addToFavourite(selectedTextView.getText());
     
}

private void addToFavourite(String title) {
     if (favourites.contains(title)) return;

     favourites.add(title);
     favouriteAdapter.submitList(favourites);
}

private void updateFavourite(String title) {
     val index = favourites.indexOf(title);
     if (index < 0) throw new NoSuchElementException("Cannot find " + title);

     favourites[index] = title
     favouriteAdapter.submitList(favourites);
}


private void deleteFavourite(String title) {
   favourites.remove(title);
   favouriteAdapter.submitList(favourites);
}

@Override
public void onDestroy() {
    recyclerView.adapter = null;
}

RecyclerView Adapter의 경우는 일반적인 구현방법을 쓰시면 되구요, 저같은 경우는 아이템이 많아지면 ListAdapter라는 것을 사용하기 때문에 submitList라는 메소드를 사용한 거구요, 그렇지 않다면, RecyclerViewAdapter안에

public void submitList(items: List<Favourites>) {
     this.items = items;
     notifyDatasetChanged();
}

이렇게 하시면 됩니다. 물론 동영상 처럼, 변경된 위치에 해당하는 notifyItem* 메소드를 호출하셔도 되구요. 저는 그냥 이런게 귀찮아서 ListAdapter를 쓴 겁니다.

spark (226,720 포인트) 님이 2020년 12월 30일 답변
개발개발자님이 2020년 12월 31일 채택됨
답변 감사합니다.
제가 JAVA를 써서 완전히 이해는 되지 않네요...
총 activity가 RecyclerView랑, itemVIew가 필요하고
JAVA파일은 Adapter가 더 필요하다는 말씀이시죠??
그럼 데이터는 어디서 관리해주어야 하나요..
저 코드는 자바코드인데요. RecyclerViewAdapter는 이미 어떻게 작성하시는지 알고 계시다고 가정한거예요.
아아 그렇네요 죄송합니다 바쁜 일 중에 급하게 보느라... 제대로 보고 답변 달았어야했는데..성의를 무시한건 아닙니다.. 다시 한 번 죄송합니다.
RecyclerViewAdapter도 가이드라인 좀 잡아 주실 수 있을까요..동영상을 보며 흐름은 익혔는데 제대로 적용하기가 힘들어서...
0 추천

먼저 https://developer.android.com/guide/topics/ui/layout/recyclerview(한글 버전도 있을 겁니다.)를 정독하시구요. Adapter와 ViewHolder를 이해하셔야 해요.
Adapter(어댑터)는 쉬운 예로 파워어댑터는, 110을 220로 변환시켜주잖아요. 한쪽은 110볼트의 소켙에, 다른 한쪽은 220에 연결할 수 있잖아요. 어댑터란 서로 다른 인터페이스의 클래스를 연결시켜주는 역할을 하는 클래스라고 보시면 됩니다.  
RecyclerViewHolder는 말그대로 뷰홀더입니다. 컵홀더가 컵을 가지고 있도록 해서 잡아주는 역할을 하듯이, 뷰홀더를 뷰를 가지고 그릴 수 있도록 해줍니다.
RecyclerView에 어떤 형태의 뷰도 출력할 수 있도록 하기위해서 어댑터 클래스를 사용하는 것입니다. 입력에 관계없이 출력을 내맘대로 조절할 수 있도록 말이죠. 그리고 이 어탭터는 실제로 화면에 그리는 실제적인 부분을 뷰홀더에게 맡깁니다. 따라서 뷰홀더가 어떻게 화면에 그리느냐에 따라 실제의 출력이 결정되는 것입니다.
이런 이유로, 어댑터는 여러개의 뷰홀더를 사용할 수 있도록 되어 있습니다. 그래야 뷰의 형태가 다른 것들을 서로 조합해서 하나의 리스트로 보여주기 쉽잖아요. 리스트가 항상 동일한 모양의 뷰만 보여주는 게 아니기 때문에 말이죠.
RecyclerView는 어댑터가 뷰홀더를 이용해 화면을 출력하기 위한 틀에 해당한다고 보시면 됩니다.

RecyclerViewAdapter의 클래스 보시면,
 

public class RecyclerView.Adapter<VH extends RecyclerView.ViewHolder>

이렇게 정의되어 있습니다. 어떤 뷰홀더를 사용할 것인지 어댑터에게 알려주는 것이죠.

public class CustomAdapter extends  RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

   private List<String> items;

   public CustomAdapter(items: List<String>) {
        this.items = items;
  }

  @Override
  public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false);

        return ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        viewHolder.textView.text = items.get(position);
    }

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

    class ViewHolder(view: View)  extends RecyclerView.ViewHolder(view) {
         public final val textView: TextView

         public ViewHolder(View itemView) {
             textView = view.findViewById(R.id.textView)
         }
    }

}

어댑터를 구현하실 때는, 먼저 RecyclerView.Adapter를 상속하셔야 합니다. 그리고 뷰홀더 클래스를 만드셔서 해당 클래스를 제너릭 타입으로 넣어주세요.

getItemCount를 오버라드 하셔서, 님이 화면에 뿌려줄 아이템의 갯수를 지정해 주세요. 만약 어댑터에 전달한 아이템 리스트의 갯수만큼 하실 거면 itemList.getSize()라고 하시면 되겠죠.

그리고 해당 아이템을 화면에 그리기 위해서 뷰홀더 클래스를 만들고 이 클래스의 인스턴스를 onCreateViewHolder 메소드에서 해줍니다.  그리고 onBindViewHolder()에서 실제 아이템을 그리는 부분을 구현해 줍니다.onBindViewHolder 메소드에서 첫번째 ViewHolder는 onCreateViewHolder에서 조금 전에 생성했던 인스턴스입니다.

 

override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(view)
    }

 onCreteViewHolder에서는 각각의 아이템의 사용할 레이아웃을 가져와서 이걸  inflate 합니다.뷰에 실제 내용을 보여주는 건 ViewHolder클래스에서 처리하시면 되구요.

 override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
        viewHolder.textView.text = dataSet[position]
}

위에서는 dataSet[position]으로 위에서 생성했던 문자열 리스트를  포지션에 맞게 읽어와서 보여주고 있습니다. 기본 흐름은 이렇구요. 리사이클러뷰의 특징은 뷰의 재사용입니다. 뷰를 메모리에 보관했다가 다시 꺼내어 쓰기위해  ViewHolder를 사용하는 겁니다. 이렇게 하게되면 아이템의 갯수가 많아져도 성능이  많아져도 속도가 확 저하되지는 않습니다.

아마 onCreateViewHolder나 onBindViewHolder에서 ViewHolder  인스턴스를 확인해 보시면, 리사이클러뷰가 뷰를 재상요하는 것을 쉽게 화인할 수 있습니다.

더 자세한 것은 개발자 사이트나 구글에서 적당한 튜토리얼을 찾아보시면 되리라 생각합니다.예제를 많이 짜보세요, 몇번 해보시면 감이 오실 겁니다.

spark (226,720 포인트) 님이 2020년 12월 31일 답변
좋은 답변 정말 감사합니다. 일단 새해 복 많이 받으시고 항상 건강하시길 기원하겠습니다.
지금 ArrayList에 데이터를 추가해서 RecyclerViewActivity에 뿌리려고 합니다 Adapter썻구요.
Fragment에 있는 문자열을 ArrayList에 넣은 다음 RecyclerViewActivity에 ArrayList를 뿌리고 싶습니다....
...