본문 바로가기
안드로이드

[안드로이드] 리사이클러뷰 데이터 바인딩 이벤트 (RecyclerView data binding)

by algosketch 2022. 1. 27.

지난 글에서 빼먹은 부분이 있다. 리사이클러뷰에서 이벤트 리스너를 연결하는 방법인데, 지금 상태에서 무지성으로 리스너를 연결한다면 아마 bind 함수에서 하게될 것이다. 이번 글에서는 Adapter 에 ViewModel 을 받아 사용하는 방법을 알아보자. 지난 글에 이어서 설명하겠다. 이번에는 지난 번보다 짧다.

 

1. 이벤트 함수 구현

class MainViewModel : ViewModel() {
    // ...

    fun showToastMessage(view: View, text: String) {
        Toast.makeText(view.context, text, Toast.LENGTH_SHORT).show()
    }
}

내가 실제로 코딩한 순서는 이것과 다르지만, 글에서는 컴파일 에러가 나지 않는 순서대로 진행할 예정이다. 함수 바디 부분은 간단해서 설명할 부분이 없고, 파라미터로 View 와 String 을 받는다는 것만 확인하고 넘어가겠다.

 

2. xml 파일에서 메소드 바인딩

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="item"
            type="org.algosketch.datebindingtest.ExampleItem" />

        <variable
            name="viewModel"
            type="org.algosketch.datebindingtest.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="여기 적힌 내용이 토스트 메시지로 출력될 거야!"
            android:text="@{item.content}"
            android:onClick="@{(view)->viewModel.showToastMessage(view, item.content)}"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

새로운 변수 viewModel 을 추가했다. Button 의 onClick 부분에서 방금 구현한 함수를 바인딩 시켜준다. 위 코드처럼 View 자신을 인자로 넘길 수 있고, 다른 인자도 추가해서 넘길 수 있다. 다만 자동완성이 안 되기 때문에 IDE 가 큰 도움이 되지는 않는다.

 

3. Adapter 에 ViewModel 추가

class ExampleAdapter(private val viewModel: MainViewModel) : RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder>() {
    // ...

    override fun onBindViewHolder(holder: ExampleViewHolder, position: Int) {
        holder.bind(viewModel, exampleList[position])
    }

    // ...

    class ExampleViewHolder private constructor(val binding: ItemExampleBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(viewModel: MainViewModel, item: ExampleItem) {
            binding.item = item
            binding.viewModel = viewModel
            binding.executePendingBindings()
        }

        // ...
    }
}

Adapter 생성자에 ViewModel 을 추가하고 bind 메소드를 통해 바인딩 시켜준다.

class MainActivity : AppCompatActivity() {
    val viewModel: MainViewModel by viewModels()
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        
        setupAdapter()
    }

    fun setupAdapter() {
        binding.exampleRecyclerView.adapter = ExampleAdapter(viewModel)
    }
}

Adapter 의 생성자가 변경되었으므로 MainActivity 또한 수정해준다. 다음 글에서는 진짜로 DiffUtil 사용 방법에 대해 작성하겠다.