[ Android Studio ] #9. 리싸이클러뷰에 대해 알아보자

ma.caron_g·2022년 1월 30일
0
post-thumbnail

[ 참고 출처 ]

[ 에뮬레이터 속 프로필 일러스트 출처 ]

[ 리싸이클러뷰란 ? ]

뷰 그룹의 한 종류로 한 화면에 표시되기 힘든 많은 수의 데이터들을 스크롤 기능을 이용하여 리스트로 표시해주는 위젯입니다.

RecyclerView는 ListView의 개선판입니다.
목록의 뷰는 ViewHolder 로 표현되며 각 ViewHolder 는 View를 사용하여 각 항목을 표시하는 역할을 한다.
ViewHolder 객체는 Adapter 에서 관리하며 Adapter 는 필요에 따라 ViewHolder 를 만들어 onBindViewHolder()를 호출함으로써 데이터에 바인딩한다.
View를 채울 때 LayoutManger 가 필요한데, LinearLayoutManager 또는 GridLayoutManager 를 쓰거나 직접 구현하여 사용하면 된다.

예전에는 이전 장의 ListView를 많이 썼지만 요즘에는 RecyclerView가 ListView의 거의 모든 기능을 대체 가능하고 더 유연해진 버전이기에 이것을 더 많이 사용합니다.

[ 왜 ListView보다 좋아? ]

리스트뷰(ListView)의 경우, 기본 가이드에 따라 구현했을 때 만날 수 있는 문제점 중의 하나는, 리스트 항목이 갱신될 때마다, 매번 아이템 뷰를 새로 구성해야 한다는 것이었습니다. 이는 "많은 수의 데이터 집합을 표시"하는데 있어서, 성능 저하를 야기할 수 있는 요인이 됩니다.

  • ListView는 수직으로만 나열이 가능하나 RecyclerView는 수평방향으로도 나열가능.
  • 아이템 뷰의 동적(Dynamic) 구성을 용이하게 만들어줌.

[ 리싸이클러뷰의 구성 ]

리사이클러뷰(RecyclerView)는
어댑터(Adapter), 레이아웃 매니저(LayoutManager), 뷰홀더(ViewHolder)로 구성되어 있습니다.

>> 어댑터 (Adapter)

데이터들을 데이터의 원본을 받아서 관리하고 뷰에 출력할 수 있는 형태로 데이터를 다시 제공하는 역할을 합니다.

>> 레이아웃 매니져 (LayoutManager)

데이터나 아이템들이 리사이클러뷰 내부에서 배치되는 형태를 관리하는 역할을 합니다.

>> 뷰홀더 (ViewHolder)

화면에 표시될 데이터나 아이템들을 저장하는 역할을 합니다.




[ 리싸이클뷰 만들기 ]

>> 0. build.gradle (Module: app) 수정

build.gradle (Module: app)에 아래의 dependencies를 추가한다.

리사이클러뷰는 v7 지원 라이브러리(v7 Support Library)에서 제공되는 위젯으로, 앞서 소개한 구성 요소들을 통해, 사용자 데이터를 리스트 형태로 화면에 표시하는 컨테이너 역할을 수행합니다. (android.support.v7.widget.RecyclerView)

dependencies {
  implementation 'com.android.support:recyclerview-v7:28.0.0'   
  implementation "androidx.recyclerview:recyclerview:1.1.0"       //androidx 버전
}

>> 1. 메인 액티비티에 리사이클러뷰 추가

  • res/layout/activity_main.xml
<androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

>> 2. 아이템 레이아웃을 추가

  • res/layout/item_recyclerview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:padding="20dp">

        <!--프로필 사진-->
        <ImageView
            android:id="@+id/profile"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:src="@drawable/id_user1"/>

        <!--이름-->
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:text="이름"
            android:textSize="16sp"
            android:textColor="#000"/>

        <!--상태 메시지-->
        <TextView
            android:id="@+id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="100dp"
            android:text="상태메시지"
            android:textSize="12sp"
            android:textColor="#444"
            android:maxLines="1"/>

    </LinearLayout>

    <!--구분선-->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginHorizontal="10dp"
        android:background="#aaa"/>

</LinearLayout>

그림과 같이 아이템이 될 데이터들을 어떻게 표현할지 레이아웃을 꾸민다.

>> 3. Data를 담을 Module생성 (생략 가능)

친구들의 정보를 담을 Data class를 생성해야 한다. 이미 구현된 class(String 등)를 사용할 경우 생략 가능하다.

  • FriendItem.java
public class FriendItem {
    String name;
    String message;
    int resourceId;

    public FriendItem(int resourceId, String name, String message) {
        this.name = name;
        this.message= message;
        this.resourceId = resourceId;
    }

    public int getResourceId() {
        return resourceId;
    }

    public String getMessage() {
        return message;
    }

    public String getName() {
        return name;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setResourceId(int resourceId) {
        this.resourceId = resourceId;
    }
}

>> 5. Adapter 구현

AdapterRecyclerView.Adapter를 상속받아 구현하고,
ViewHolderRecyclerView.ViewHolder를 상속받아 구현한다.

  • MyRecyclerAdapter.java
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {

    private ArrayList<FriendItem> mFriendList;

    @NonNull
    @Override
    public MyRecyclerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyRecyclerAdapter.ViewHolder holder, int position) {
        holder.onBind(mFriendList.get(position));
    }

    public void setFriendList(ArrayList<FriendItem> list){
        this.mFriendList = list;
        notifyDataSetChanged();
    }

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

    class ViewHolder extends RecyclerView.ViewHolder {
        ImageView profile;
        TextView name;
        TextView message;

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

            profile = (ImageView) itemView.findViewById(R.id.profile);
            name = (TextView) itemView.findViewById(R.id.name);
            message = (TextView) itemView.findViewById(R.id.message);
        }

        void onBind(FriendItem item){
            profile.setImageResource(item.getResourceId());
            name.setText(item.getName());
            message.setText(item.getMessage());
        }
    }
}

>> 5. 리싸이클뷰에 Adapter와 LayoutManager 연결

RecyclerView가 들어갈 MainActivity에 Adapter와 LayoutManager를 연결해준다. LinearLayoutManager 를 사용했으며 방향을 따로 설정하지 않을 시 default는 VERTICAL 이다.

  • MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);

    /* initiate adapter */
    mRecyclerAdapter = new MyRecyclerAdapter();

    /* initiate recyclerview */
    mRecyclerView.setAdapter(mRecyclerAdapter);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}

💡LinearLayoutManager의 방향을 HORIZONTAL 로 하고 싶은 경우
mRecyclerView.setLayoutManager(new LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)); 를 사용하면 된다.

>> 6. Sample Data를 넣고 작동 확인

구현만 한다고 RecyclerView의 작동을 바로 확인할 수 있는 것은 아니다. 임의의 데이터를 넣어 잘 작동하는지 확인한다.
데이터가 변경된 후에는 Adapter의 notifyDataSetChanged()를 호출하여 데이터가 변경되었음을 꼭 알려야한다.
나는 MyRecyclerAdapter에 데이터를 연결하고 notifyDataSetChanged()를 호출하는 메소드 setFriendList()를 만들어 MainActivity에서 setFriendList()를 호출하는 방식을 사용했다.

  • MainActivity.java
for(int i=1;i<=20;i++){
            switch(i%8){
                case 0 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user8,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 1 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user1,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 2 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user2,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 3 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user3,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 4 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user4,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 5 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user5,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 6 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user6,i+"번째 사람",i+"번째 상태메시지"));
                    break;
                case 7 :
                    mfriendItems.add(new FriendItem(R.drawable.id_user7,i+"번째 사람",i+"번째 상태메시지"));
                    break;
        }
}
mRecyclerAdapter.setFriendList(mfriendItems);

profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글