스터디/Android+Kotlin

안드로이드 코틀린 RecyclerView에 데이터바인딩 사용하기

Dalmangyi 2020. 7. 21.

안녕하세요!

오늘은 안드로이에서 코틀린으로 RecyclerView를 작성할때 데이터 바인딩을 사용해 보도록 하겠습니다.

 

계속 이어저온 프로젝트에 바로 데이터 바인딩을 하기엔.. 아직 저도 미숙해서 

일단 간단한 리사이클러뷰에 도입을 해가면서 과정을 보여드리려고 해요

 

 

 

 

 

1. 간단한 리사이클러뷰 데이터바인딩으로 만들기

 

1-1) 프로젝트 생성

BindRecyclerView 라는 이름으로 생성해 봅니다

패키지명 : com.example.bindrecyclerview

 

 

 

 

1-2) build.gradle (:app)

apply plugin: "kotlin-kapt"

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    dataBinding {
        enabled = true
    }

	...
    
}

dependencies {
   
    ...

    implementation "androidx.recyclerview:recyclerview:1.1.0"

}

build.gradle

app단에 있는 build.gradle파일에

kotlin-kapt 플러그인 적용, 데이터바인딩 옵션과 RecyclerView 디펜던시를 추가해줍니다

 

 

 

 

 

 

1-3) 매니페스트에 액티비티 추가하기

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bindrecyclerview">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <activity android:name=".ActivityMain">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        
    </application>

</manifest>

AndroidManifest.xml 

 

앱 실행시 ActivityMain 액티비티가 실행될 수 있도록 <activity><intent-filter><action><category>를 추가해줍니다

 

 

 

 

 

 

1-4) 뷰모델 만들기

package com.example.bindrecyclerview

import androidx.databinding.ObservableArrayList

class MainViewModel {
    val items = ObservableArrayList<String>()
    init {
        items.add("고길동")
        items.add("김철수")
        items.add("달망이")
    }
}

MainViewModel.kt

데이터를 감시하는 뷰모델을 만들고 RecyclerView의 리스트를 담당할 items를 만들어줍니다.

이때 변화를 감지할 수 있게 ObservableArrayList 형태로 만들어 줍니다.

초기데이터로 3명의 사람 이름을 집어넣습니다 :-)

 

 

 

 

 

 

 

1-5) Activity XML 만들기

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="mainVM"
            type="com.example.bindrecyclerview.MainViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:bind_items="@{mainVM.items}"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    </RelativeLayout>
</layout>

activity_main.xml

<data><variable>태그를 추가하여 MainViewModel을 mainVM이란 이름으로 정해줍니다.

화면 전체에는 RelativeLayout과 RecyclerView를 추가합니다.

RecyclerView에는 app:bind_items 라는 CustomAttribute를 추가해 줍니다.

 

 

 

 

 

 

1-6) RecyclerView Item XML 만들기

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/mRootView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="20dp">

    <TextView
        android:id="@+id/mName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

recyclerview_item.xml

RecyclerView의 item(한 칸)을 차지할 디자인을 만들어줍니다.

가운데 이름이 적혀있는 텍스트뷰만 존재하는 디자인 입니다.

 

 

 

 

 

 

1-7) ViewHolder 만들기

package com.example.bindrecyclerview

import android.view.View
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.recyclerview_item.view.*

class ContactsViewHolder(v: View) : RecyclerView.ViewHolder(v){
    var view : View = v

    fun bind(item: String) {
        view.mName.text = item
    }
}

ContactsViewHolder.kt

화면을 그릴 ViewHolder를 만듭니다.

bind함수가 호출되면 인자로 받은 item을 뷰의 이름으로 설정해줍니다.

 

 

 

 

 

 

1-8) Adapter 만들기

package com.example.bindrecyclerview

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

class ItemAdapter : RecyclerView.Adapter<ContactsViewHolder>() {
    var items : List<String> = emptyList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactsViewHolder {
        val inflatedView = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item, parent, false)
        return ContactsViewHolder(inflatedView)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: ContactsViewHolder, position: Int) {
        val item = items[position]

        holder.apply {
            bind(item)
        }
    }
}

ItemAdapter.kt

RecyclerView에서 사용하는 RecyclerView.Adapter를 상속 받습니다 

보여줄 데이터를 items 로 관리하고 있고

Adapter의 기존 3개 함수를 오버라이드 합니다

onCreateViewHolder()는 뷰홀더를 만들고

getItemCount()는 아이템 갯수를 반환합니다

그리고 onBindViewHolder()에는 데이터를 뷰홀더에 반영하는 역활을 해줍니다

 

 

 

 

 

 

 

1-9) DataBinding Util 

package com.example.bindrecyclerview

import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView

object DataBindingUtils {

    @JvmStatic
    @BindingAdapter("bind_items")
    fun setBindItems(view : RecyclerView, items : List<String>) {
        val adapter = view.adapter as? ItemAdapter ?: ItemAdapter().apply { view.adapter = this }
        adapter.items = items
        adapter.notifyDataSetChanged()
    }
}

DataBindingUtils.kt

activity_main.xml에서 recyclerview에 사용되던 CustomAttribute를 여기서 선언해줍니다

class가 아닌 object로 하고 @JvmStatic 어노테이션을 추가합니다

선언할때는 @BindingAdapter어노테이션을 사용하여 xml에서 사용할 수 있게 됩니다 

호출되는 시점의 RecyclerView에 할당된 adapter를 가져와서 ItemAdapter로 캐스팅해줍니다. 그리고 view.adapter에 다시 ItemAdapter를 삽입해줍니다.

아이템들을 세팅해주고 화면을 갱신합니다

 

 

 

 

 

 

1-10) MainActivity 만들기

package com.example.bindrecyclerview

import android.app.Activity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.bindrecyclerview.databinding.ActivityMainBinding

class ActivityMain : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.mainVM = MainViewModel()

    }

}

MainActivity.kt

Activity를 상속받아서 binding에 mainVM을 MainViewModel로 지정해 줍니다

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글