웹사이트 검색

Android RecyclerView 데이터 바인딩


이 자습서에서는 Android 애플리케이션에서 데이터 바인딩을 사용하여 RecyclerView를 논의하고 구현합니다.

Android RecyclerView DataBinding

Android DataBinding의 기본 사항을 알아보려면 어댑터 클래스를 방문하세요. 마지막으로 XML에서 어댑터 개체를 직접 전달하는 방법을 보여줍니다.

시작하기

앱의 build.gradle에 다음 코드를 추가하세요.

android{
...
dataBinding {
        enabled = true
    }
...
}

다음 종속성을 추가합니다.

implementation 'com.android.support:design:28.0.0'

프로젝트 구조

암호

DataModel.java 클래스의 코드는 다음과 같습니다.

package com.journaldev.androidrecyclerviewdatabinding;

public class DataModel {

    public String androidVersion, androidName;

    public DataModel(String androidName, String androidVersion) {

        this.androidName = androidName;
        this.androidVersion = androidVersion;
    }
}

activity_main.xml 레이아웃의 코드는 다음과 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">

    <data>
        
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

MainActivity.java

package com.journaldev.androidrecyclerviewdatabinding;

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

import com.journaldev.androidrecyclerviewdatabinding.databinding.ActivityMainBinding;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        populateData();
    }

    private void populateData() {
        List<DataModel> dataModelList = new ArrayList<>();

        dataModelList.add(new DataModel("Android Oreo", "8.1"));
        dataModelList.add(new DataModel("Android Pie", "9.0"));
        dataModelList.add(new DataModel("Android Nougat", "7.0"));
        dataModelList.add(new DataModel("Android Marshmallow", "6.0"));

        MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this);
        binding.setMyAdapter(myRecyclerViewAdapter);
    }
}

RecyclerView의 각 행에 대한 레이아웃은 item_row.xml에 정의되어 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="model"
            type="com.journaldev.androidrecyclerviewdatabinding.DataModel" />

        <variable
            name="itemClickListener"
            type="com.journaldev.androidrecyclerviewdatabinding.CustomClickListener" />
    </data>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="@{() -> itemClickListener.cardClicked(model)}"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_margin="8dp"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tvAndroidName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{model.androidName}"
                android:textAppearance="@style/TextAppearance.AppCompat.Headline" />

            <TextView
                android:id="@+id/tvAndroidVersion"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{model.androidVersion}"
                android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />

        </LinearLayout>

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

</layout>

데이터 태그 내에서 DataModel 참조와 CardView에서 메서드가 호출되는 CustomClickListener 인터페이스의 참조라는 두 개의 변수를 전달합니다. CustomClickListener.java의 코드는 다음과 같이 정의됩니다.

package com.journaldev.androidrecyclerviewdatabinding;

public interface CustomClickListener {
    void cardClicked(DataModel f);
}

MyRecyclerViewAdapter.java 클래스의 코드는 다음과 같습니다.

package com.journaldev.androidrecyclerviewdatabinding;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.List;

import com.journaldev.androidrecyclerviewdatabinding.databinding.ItemRowBinding;

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> implements CustomClickListener {

    private List<DataModel> dataModelList;
    private Context context;

    public MyRecyclerViewAdapter(List<DataModel> dataModelList, Context ctx) {
        this.dataModelList = dataModelList;
        context = ctx;
    }

    @Override
    public MyRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                               int viewType) {
        ItemRowBinding binding = DataBindingUtil.inflate(
                LayoutInflater.from(parent.getContext()),
                R.layout.item_row, parent, false);

        return new ViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        DataModel dataModel = dataModelList.get(position);
        holder.bind(dataModel);
        holder.itemRowBinding.setItemClickListener(this);
    }


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

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ItemRowBinding itemRowBinding;

        public ViewHolder(ItemRowBinding itemRowBinding) {
            super(itemRowBinding.getRoot());
            this.itemRowBinding = itemRowBinding;
        }

        public void bind(Object obj) {
            itemRowBinding.setVariable(BR.model, obj);
            itemRowBinding.executePendingBindings();
        }
    }

    public void cardClicked(DataModel f) {
        Toast.makeText(context, "You clicked " + f.androidName,
                Toast.LENGTH_LONG).show();
    }
}

데이터를 XML 상대에게 전달하기 위해 itemRowBinding.setVariable(BR.model, obj);를 사용하여 바인딩합니다. 데이터 바인딩을 즉시 실행하려면 executePendingBindings()가 중요합니다. 그렇지 않으면 잘못된 보기를 채울 수 있습니다.

setVariable()과 setModel()의 차이점 setVariable()은 데이터 유형을 알 수 없는 일반적인 상황에서 사용됩니다. setModel()은 자동 생성됩니다. holder.bind(dataModel); 대신 다음을 사용할 수 있습니다.

holder.itemRowBinding.setModel(dataModel);

데이터 결합을 사용하여 RecyclerView XML에서 어댑터 인스턴스 전달

데이터 바인딩 덕분에 아래와 같이 android:adapter 속성 내부의 XML에 있는 어댑터 인스턴스를 전달하여 MainActivity.java의 상용구 코드를 더 줄일 수 있습니다. >activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto">


    <data>

        <variable
            name="myAdapter"
            type="com.journaldev.androidrecyclerviewdatabinding.MyRecyclerViewAdapter" />
    </data>


    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adapter="@{myAdapter}"
            app:layoutManager="android.support.v7.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>
</layout>

MainActivity.java에서 이제 다음과 같은 방식으로 어댑터를 설정할 수 있습니다.

MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(dataModelList, this);
binding.setMyAdapter(myRecyclerViewAdapter);

AndroidRecyclerViewDataBinding

Github 프로젝트 링크