2019/04/14 - [Android] - 안드로이드 리사이클러뷰(RecyclerView) 사용법 (1)

 

지난 글에 이어서 리사이클러뷰의 아이템부터 알아보겠다.

 

 

/* item.xml */

 


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:orientation="horizontal">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:text="제목" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:text="내용" />
</LinearLayout>

 

- [layout] -> [new] -> [Layout Resource File] 로 .xml 레이아웃 파일을 하나 생성한다.

 

- 아이템은 간단한 예시로 이미지뷰 1개, 텍스트뷰 2개로 구성하였다. 여기서 리스트뷰에 표시할 한 아이템의 레이아웃을 만들면 된다. 

 

 

 

 

 

 

/* RecyclerViewA.java */

 


package com.tistory.godog.test2;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class RecyclerViewA extends RecyclerView.Adapter<RecyclerViewA.ViewHolder> {

    private String[] title = {"제목1", "제목2", "제목3", "제목4",
            "제목5", "제목6", "제목7", "제목8", "제목9", "제목10", };

    private String[] content = {"내용1", "내용2", "내용3", "내용4",
            "내용5", "내용6", "내용7", "내용8", "내용9", "내용10", };

    public class ViewHolder extends  RecyclerView.ViewHolder {
        public TextView textView;
        public TextView textView2;
        public ImageView imageView;

        public ViewHolder(View view) {
            super(view);
            this.textView = view.findViewById(R.id.textView);
            this.textView2 = view.findViewById(R.id.textView2);
            this.imageView = view.findViewById(R.id.imageView);
        }
    }

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

    @Override
    public void onBindViewHolder(RecyclerViewA.ViewHolder holder, final int position) {
        holder.textView.setText(title[position]);
        holder.textView2.setText(content[position]);

        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), position+"번 째 이미지!", Toast.LENGTH_SHORT).show();
            }
        });

        holder.textView2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), "Test!", Toast.LENGTH_SHORT).show();
            }
        });

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(v.getContext(), position+"번 째!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return title.length;
    }
}

 

1. 자바(.java) 파일을 추가합니다.

 

2. RecyclerView.Adapter<RecyclerView.ViewHolder>를 상속 받습니다.

 

3. [Ctrl]+[I] 3개의 메소드를 추가해줍니다.

 

4. 19라인의 RecyclerView.ViewHolder를 상속받은 클래스를 선언한 후 item에서 뷰객체 변수를 선언한 후 연결해 줍니다.

 

5. 2번에서 상속하였던 <RecyclerView.ViewHolder> 부분을 <자바파일명.4번의 선언한 클래스명>으로 수정해줍니다.

 

 

여기까지 진행하였다면 전반적인 구조는 끝이난다.

 

 

onCreateViewHolder() : 이곳은 LayoutManager에 의해 새 아이템을 만들 때 호출하며, 이 아이템뷰의 ViewHolder를 만들어준다.

 

onBindViewHolder() : LayoutManager에 의해 ViewHolder에 position에 맞는 데이터를 이용하여 리스트를 채우게 된다.

 

getItemCount() : 보통 메소드 이름처럼 리사이클러뷰의 표시할 데이터(아이템)의 개수를 리턴 한다.

 

 

 

- holder에서 연결한 item의 뷰 객체들은 onBindViewHolder() 메소드내에서 onClick()등 액션에 대한 실행을 지정할 수 있습니다.

 

아래 이미지는 이미지 뷰, 텍스트 뷰, 아이템에 따라 클릭하였을 때 다른 결과를 확인 할 수 있습니다.

 

이렇듯 리사이클러뷰를 사용하면 간단하게 각 아이템마다 액션을 설정하거나 아이템 내 각각의 뷰마다 액션을 간단히 설정 할 수도 있다.

 

T리사이클러뷰를 이용하여 커스텀 리스트를 만들어 본다.

 

실행 화면

- 리사이클러뷰(RecyclerView)는 기존의 사용하던 리스트뷰(ListView)의 단점들을 보완한 레이아웃이다.

 

- 단점들을 보완하여 만들어진만큼 기존의 커스텀 리스트뷰를 만들 때에 복잡함을 줄여 리스트를 만들 수 있다. ( 데이터를 관리하는 것과 UI를 표현하는 것이 분리가 되어있으므로 번거로운 기존의 수정 방식을 피할 수 있고 에러도 줄일 수 있다.)

 

 

 

 

리사이클러뷰(RecyclerView)

- 이름 그대로 리사이클(재활용)하므로 많은 양의 데이터를 표시하여도 메모리가 부족하게 되어 프로그램이 강제로 종료되는 상황을 막을 수 있다.

(이는 가끔 앱들을 사용하면서 화면을 내릴 때 화면이 버벅거리는 현상들을 발생시킨다.)

 

 

- 재활용이란 위 2개의 이미지를 보면 이해하기 편한데 첫 번째 이미지를 보면 1번 뷰와 같이 스크롤을 내려 보이지 않는 뷰도 메모리를 계속 사용하고 있다.

 

하지만 리사이클 뷰는 두 번째 이미지처럼 지나친 1번 뷰를 다시 아래로 재사용함으로써 메모리 문제를 해결하도록 만들어 준다.

 

 

 

 

 

 

 리사이클뷰를 사용하기 위해서는 우선 라이브러리를 추가해주어야 한다.

 

implementation 'com.android.support:recyclerview-v7:27.1.1'

 

직접 추가해주어도 상관없지만 아래 글을 참조하여 추가해주면 더욱 좋을 것이다.

 

2019/04/03 - [안드로이드] - 안드로이드 스튜디오 라이브러리 추가

 

 

 

 

 

 그러면 먼저 프로젝트 생성 시 만들어지는 메인 레이아웃과 메인 자바 파일을 살펴보겠다.

 

 

 

/* 메인 레이아웃( activity_main.xml ) */

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/rel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="40dp">

        </android.support.v7.widget.RecyclerView>

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/recycler_view"
            android:text="hoxy" />
    </RelativeLayout>
</LinearLayout>

 

- android.support.v7.widget.RecyclerView로 리사이클러뷰를 추가하였다. Design 탭의 Palette의 검색하여서 추가할 수도 있다.

 

- 위 코드를 보면 굳이 RelativeLayout 속에 리사이클러뷰와 버튼을 추가하였다. 이는 리사이클러뷰 밑에 버튼 추가 시 보이지 않는 문제를 해결하기 위해서이다.

( 아마도 버튼이 리사이클러뷰 아래로 가서 보이지 않는 것 같다. 버튼을 먼저 삽입하고 리사이클러뷰를 삽입하면 버튼이 보인다.)

 

- 리사이클러뷰에서 paddingBottom을 40dp 준 이유도 마찬가지이다. 이를 한번 빼보고 실행해보는 것도 좋을 것이다.

 

 

 

 

 

 

/* 메인 자바 코드 ( MainActivity.java ) */

package com.tistory.godog.test2;


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;


public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    public RecyclerView.LayoutManager layoutManager;
    private RecyclerView.Adapter adapter;

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

        recyclerView = findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);

        //layoutManager = new GridLayoutManager(this, 1);
        layoutManager = new LinearLayoutManager(this);
     

        recyclerView.setLayoutManager(layoutManager);

        adapter = new RecyclerViewA();
        recyclerView.setAdapter(adapter);
    }
}

 

- 변수 선언 

 12라인 : 리사이클러뷰 변수를 선언

 13라인 : 리사이클러뷰 변수와 연결하여 관리할 레이아웃 매니저 변수 선언

 14라인 : 리사이클러뷰 어뎁터 선언

 

- 설정

 22라인 : .setHasFixedSize(true) 메서드는 리사이클러뷰 안 아이템들의 크기를 가변적으로 바꿀지 아니면 일정한 크기를 사용할지를 지정한다.

 이를 false로 준다면 매번 아이템들의 크기를 계산해야 하므로 성능 저하에 영향을 미칠 수 있다. 그리고 디자인적으로도 크기가 다 같은 것이 좋으니 true를 주는 게 좋다.

 

 

 24/25라인 : 레이아웃 매니저의 타입을 지정해준다. 24라인 주석처리가 된

  new GridLayoutManager(this, 1)는 그리드형으로 보여준다. 그리드형이라고 한다면 쉽게 말해서

  m x n 형태이다. 여기서 2번 째로 주는 인수열의 개수이다.

 

 25라인 : new LinearLayoutManager(this)는 우리가 생각하는 그 리스트형으로 설정에 따라서 가로 혹은 세로로 표시할 수 있다.

 

 

 28라인  : 리사이클러뷰와 레이아웃 매니저를 연결해준다.

 

 

 30라인 : 여기서는 어뎁터 객체를 생성하는데, 이는 추후의 추가할 어뎁터 자바 파일명이다.

 

 31라인 : 리사이클러뷰의 어뎁터를 연결해준다.

 

 

 

 

다음 글에서 이어집니다 

 

2019/04/14 - [Android] - 안드로이드 리사이클러뷰(RecyclerView) (2)

 

+ Recent posts