일기장
Android MVVM, RecyclerView + Livedata + databinding (Kotlin) 본문
1. app gradle에 databinding 추가
buildFeatures{
dataBinding = true
}
2. 기본적인 ViewModel과 Data Class 작성
class MainViewModel: ViewModel() {
private val _postList = ListLiveData<PostModel>()
val postList: LiveData<ArrayList<PostModel>>
get() = _postList
…
}
data class PostModel (
val postId: String
)
3. RecyclerView에 databinding (posts 속성은 아래 BindingAdapter로 추가)
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/post_list"
…
posts="@{vm.postList}"
…
/>
4. RecyclerView에 사용될 Item xml 작성
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="postItem"
type="com.example.test.api.model.PostModel" />
</data>
…
</layout>
5. Binding된 변수의 변화를 RecyclerViewAdapter에게 알리는 Custom Binding Adapter 작성
…
@JvmStatic
@BindingAdapter("posts")
fun setBindPost(view: RecyclerView, posts: LiveData<ArrayList<PostModel>>) {
view.adapter?.run {
if(this is PostListAdapter) {
posts.value?.let { this.posts = it } ?: { this.posts = arrayListOf() }()
this.notifyDataSetChanged()
}
}
}
…
6. RecyclerViewAdapter 작성
class PostListAdapter(val vm: MainViewModel): RecyclerView.Adapter<PostListAdapter.PostHolder>() {
var posts = ArrayList<PostModel>()
set(value) {
posts.clear()
posts.addAll(value)
}
inner class PostHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val binding: PostItemBinding? = DataBindingUtil.bind(itemView)
fun bind(item: PostModel) {
binding?.setVariable(BR.postItem, item)
// post item click listener
itemView.setOnClickListener {
vm.onPostClick(item)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = PostHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.post_item,
parent,
false
)
)
override fun getItemCount() = posts.size
override fun onBindViewHolder(holder: PostHolder, position: Int) {
holder.bind(posts[position])
}
}
7. Activity혹은 Fragment에서 Adapter 선언
…
val mViewModel: MainViewModel by activityViewModels()
post_list.adapter = PostListAdapter(mViewModel)
…