안녕하세요.
오늘은 안드로이드에서 많이 사용하는 리사이클러뷰를 데이터바인딩 라이브러리와 함께 사용하는 방법에 대해 알아보겠습니다.
(이 글은 리사이클러뷰를 사용할 줄 안다는 전제하에 작성하였습니다.)
* Data Binding Library 이란?
데이터 바인딩은 안드로이드에서 제공하는 라이브러리로
액티비티 코드 내에서 UI 컴포넌트에 데이터를 붙이는 것이 아니라
레이아웃에서 UI 컴포넌트와 데이터를 연결시켜놓을 수 있습니다.
- 기존 연결 방법
findViewById<TextView>(R.id.sample_text).apply {
text = viewModel.userName
}
- 데이터 바인딩
<TextView
android:text="@{viewmodel.userName}" />
빈 프로젝트를 새로 생성한 후 데이터바인딩을 사용하기 위해
build.gradle(module) 파일에 아래 코드를 입력해줍니다.
buildFeatures{
dataBinding true
}
같은 파일에서 plugins{} 안에 아래 코드가 있는지 확인하고 없다면 추가해줍니다.
id 'kotlin-kapt'
뉴스앱을 만든다고 가정하고 LargeNews 라는 클래스를 생성해보겠습니다.
리사이클러뷰의 아이템에 사용할 LargeNews 라는 이름의 data class를 추가해줍니다.
data class LargeNews(
val title: String,
val image: Drawable?
)
다음으로 액티비티 또는 프래그먼트에 리사이클러뷰를 추가해보겠습니다.
- MainActivity.kt 생성
- activity_main.xml 생성 후 리사이클러뷰 추가
- activity_main.xml 의 최상단의 <?xml…?> 부근 왼쪽 가장자리를 클릭하면 전구가 표시되고 (또는 Alt+Enter 누름) "convert to data binding layout"을 클릭합니다. (직접 레이아웃의 가장 바깥을 <layout></layout> 으로 감싸도 됩니다.)
완성된 레이아웃은 아래와 같습니다.
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvNews"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
다음으로 리사이클러뷰 아이템 레이아웃을 만들어보겠습니다.
데이터 바인딩을 위해 <data> 태그를 추가해줍니다.
<data> 태그 내의 타입은 pakage_name.class_name 입니다.
<data> 태그를 추가하면 아래와 같이 레이아웃 내에서 변수를 사용할 수 있습니다.
//Backgroud to ImageView
android:background="@{largeNews.image}"
or
//Text to TextView
android:text="@{largeNews.title}"
아이템의 최종 레이아웃은 아래와 같습니다.
<?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"
xmlns:tools="http://schemas.android.com/tools">
<!-- 데이터 바인딩에 사용할 데이터 선언 -->
<data>
<variable
name="largeNews"
type="com.canonal.news.model.LargeNews" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@color/gray"
android:padding="12dp">
<ImageView
android:id="@+id/ivLargeNews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@{largeNews.image}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="@drawable/android_icon" />
<TextView
android:id="@+id/tvTitleLargeNews"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{largeNews.title}"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivLargeNews"
tools:text="Large News Title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
레이아웃을 만들었으니 adapter와 viewholder를 만들어보겠습니다.
뷰홀더를 어댑터 내부에서 만들 수 있지만 분리해서 만들어보겠습니다.
RecyclerView.Viewholder 를 상속받는 LargeNewsViewHolder 클래스를 만들어보겠습니다.
데이터바인딩을 사용하기 위해 ItemLargeNewsBinding를 매개변수로 받겠습니다.
그리고 bind 함수를 만들어 LargeNews를 매개변수로 얻습니다.
이 함수는 객체를 레이아웃에 바인딩합니다. (= 데이터와 레이아웃을 연결시켜줍니다.)
class LargeNewsViewHolder(
private val binding: ItemLargeNewsBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(largeNews: LargeNews) {
binding.largeNews = largeNews
}
}
어댑터 클래스는 반드시 RecyclerView.Adapter<your_view_holder_class_name> 클래스를 상속받아야합니다.
그리고 아래 3개의 함수를 ovveride 해줍니다.
- onCreateViewHolder: 새 아이템을 만듭니다.
- onBindViewHolder: 연결된 위치(position)에 데이터를 연결시켜줍니다.
- getItemCount: 아이템리스트의 사이즈를 알려줍니다.
어댑터의 최종 코드입니다.
package com.canonal.news.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.canonal.news.databinding.ItemLargeNewsBinding
import com.canonal.news.model.LargeNews
class NewsAdapter(
private val largeNewsList: List<LargeNews>
) : RecyclerView.Adapter<LargeNewsViewHolder>() {
private lateinit var binding: ItemLargeNewsBinding
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LargeNewsViewHolder {
binding = ItemLargeNewsBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return LargeNewsViewHolder(binding)
}
override fun onBindViewHolder(holder: LargeNewsViewHolder, position: Int) {
val largeNews = largeNewsList[position]
holder.bind(largeNews)
}
override fun getItemCount(): Int = largeNewsList.size
}
마지막으로 메인 액티비티에서 getDummyData 함수로 데이터를 가져옵니다.
그리고 어댑터 객체를 만들고
리사이클러뷰에 이 어댑터 객체를 연결해줍니다.
또한 리사이클러뷰에 레이아웃 매니저를 만들어줍니다.
package com.canonal.news
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.canonal.news.adapter.NewsAdapter
import com.canonal.news.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val recyclerViewNews = binding.rvNews
val largeNews = DummyData.getDummyData(this)
val newsAdapter = NewsAdapter(largeNews)
recyclerViewNews.adapter = newsAdapter
recyclerViewNews.layoutManager = LinearLayoutManager(this)
recyclerViewNews.setHasFixedSize(true)
}
}
'안드로이드 코틀린' 카테고리의 다른 글
[Kotlin] onBackPressed() deprecated , 대체할 메서드는? (0) | 2022.12.12 |
---|---|
[Kotlin][Android] 키보드 열고 닫을 때 view를 부드럽게 이동시키기 (0) | 2022.12.03 |
[Kotlin][Android] Jetpack Compose에서 폰트 추가해서 사용하기 (0) | 2022.11.03 |
[Kotlin][Android] 인앱 업데이트 (0) | 2022.10.19 |
[Kotlin] 알림 구현 - Action Button & Broadcast Receiver (0) | 2022.10.09 |