이번에는 Android Jetpack - 4편에 설명한 Data Binding을 ViewModel + LiveData를 활용해서 구현해보겠다.
본인이 이해한 것이 정확하지 않을 수 있어서 참고만 하길 바란다.
예제로는 간단히 YouTube처럼 좋아요와 싫어요 개수를 구하고 총합계를 구하는 예제로 해보겠다.
# 사용법
1. bulid.gradle (Module) 추가
android {
...
dataBinding {
enabled = true
}
}
2. ViewModel + LiveData 생성
package com.example.databinding_ex.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel(){
var likeCount : MutableLiveData<Int> = MutableLiveData()
var noLikeCount : MutableLiveData<Int> = MutableLiveData()
var totLikeCount : MutableLiveData<Int> = MutableLiveData()
init {
likeCount.value = 0
noLikeCount.value = 0
totLikeCount.value = 0
}
// 좋아요 버튼
fun likeAdd(){
likeCount.value = likeCount.value?.plus(1)
totLikeCount.value = likeCount.value?.minus(noLikeCount.value!!)
}
// 싫어요 버튼
fun noLikeAdd(){
noLikeCount.value = noLikeCount.value?.plus(1)
totLikeCount.value = likeCount.value?.minus(noLikeCount.value!!)
}
// 초기화 버튼
fun reset(){
totLikeCount.value = 0
likeCount.value = 0
noLikeCount.value = 0
}
}
수정이 가능한 MutableLiveData를 생성해준다. 그 후 좋아요, 싫어요, 초기화 버튼을 눌렀을 때 실행할 함수들을 만들어준다.
3. activity.xml / string.xml 삽입 및 수정
<activity_main.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="viewModel"
type="com.example.databinding_ex.viewmodel.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/like"
android:layout_width="45dp"
android:layout_height="65dp"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:src="@drawable/ic_thumb_up"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="25dp"
android:text="@{@string/Count(viewModel.likeCount)}"
android:textSize="20sp"
app:layout_constraintStart_toEndOf="@+id/like"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/noLike"
android:layout_width="45dp"
android:layout_height="65dp"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:src="@drawable/ic_thumb_down_24"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/like" />
<Button
android:id="@+id/reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="45dp"
android:layout_marginEnd="35dp"
android:text="초기화"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{@string/Count(viewModel.noLikeCount)}'
android:textSize="20sp"
android:layout_marginStart="15dp"
android:layout_marginTop="45dp"
app:layout_constraintStart_toEndOf="@+id/noLike"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/TotCount(viewModel.totLikeCount)}"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/noLike" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<strings.xml> (res -> values -> strings.xml)
<resources>
<string name="app_name">DataBinding_EX</string>
<string name="Count">%d 개</string>
<string name="TotCount">총합 : %d 개</string>
</resources>
<data> 태그 안에 <variable>에 위에서 만들어준 viewModel을 선언해준다.
그 후 TextView안에 text를 string format을 사용해 넣어준다.
4. MainActivity.kt 작성
package com.example.databinding_ex
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProvider
import com.example.databinding_ex.databinding.ActivityMainBinding
import com.example.databinding_ex.viewmodel.MainViewModel
class MainActivity : AppCompatActivity() {
// by lazy로 값을 선언 해준 후 ViewModelProvider로 ViewModel를 만든다
private val viewModel: MainViewModel by lazy {
ViewModelProvider(this).get(MainViewModel::class.java)
}
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewModel = viewModel
binding.lifecycleOwner = this
binding.like.setOnClickListener {
viewModel.likeAdd()
}
binding.noLike.setOnClickListener {
viewModel.noLikeAdd()
}
binding.reset.setOnClickListener {
viewModel.reset()
}
}
}
ViewModelProvider로 ViewModel을 만들어준다.
각 버튼에 ViewModel에서 만들어준 함수들을 실행한다.
만약 여기서 값들이 변경될 때 어떠한 작업을 하고 싶으면 아래와 같이 observe를 달아주면 된다.
private fun observerViewModel(){
// 좋아요 개수
viewModel.likeCount.observe(this,object : Observer<Int>{
override fun onChanged(likeCount: Int?) {
Log.d(TAG,"likeCount 변경 됨 likeCount 값 : $likeCount" )
}
})
// 싫어요 개수
viewModel.noLikeCount.observe(this, object : Observer<Int>{
override fun onChanged(noLikeCount: Int?) {
Log.d(TAG,"noLikeCount 변경 됨 noLikeCount 값 : $noLikeCount" )
}
})
// 총 개수
viewModel.totLikeCount.observe(this, object : Observer<Int>{
override fun onChanged(totLikeCount: Int?) {
Log.d(TAG,"totLikeCount 변경 됨 totLikeCount 값 : $totLikeCount" )
}
})
}
전체 MainActivity 코드
package com.example.databinding_ex
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.databinding_ex.databinding.ActivityMainBinding
import com.example.databinding_ex.viewmodel.MainViewModel
class MainActivity : AppCompatActivity() {
// by lazy로 값을 선언 해준 후 ViewModelProvider로 ViewModel를 만든다
private val viewModel: MainViewModel by lazy {
ViewModelProvider(this).get(MainViewModel::class.java)
}
private lateinit var binding: ActivityMainBinding
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewModel = viewModel
binding.lifecycleOwner = this
binding.like.setOnClickListener {
viewModel.likeAdd()
}
binding.noLike.setOnClickListener {
viewModel.noLikeAdd()
}
binding.reset.setOnClickListener {
viewModel.reset()
}
observerViewModel()
}
private fun observerViewModel(){
// 좋아요 개수
viewModel.likeCount.observe(this,object : Observer<Int>{
override fun onChanged(likeCount: Int?) {
Log.d(TAG,"likeCount 변경 됨 likeCount 값 : $likeCount" )
}
})
// 싫어요 개수
viewModel.noLikeCount.observe(this, object : Observer<Int>{
override fun onChanged(noLikeCount: Int?) {
Log.d(TAG,"noLikeCount 변경 됨 noLikeCount 값 : $noLikeCount" )
}
})
// 총 개수
viewModel.totLikeCount.observe(this, object : Observer<Int>{
override fun onChanged(totLikeCount: Int?) {
Log.d(TAG,"totLikeCount 변경 됨 totLikeCount 값 : $totLikeCount" )
}
})
}
}
조금 더 좋은 방법이 있을 거 같은데 아직 실력이 부족해서 이 정도로 해보았다.
다음에는 MVVM패턴을 이용해 활용해 보겠다.
GitHub - JiSeokYeom/DataBinding_EX
Contribute to JiSeokYeom/DataBinding_EX development by creating an account on GitHub.
github.com
참고 자료
https://webcache.googleusercontent.com/search?q=cache:oX_8a_7twLkJ:https://hanyeop.tistory.com/214+&cd=2&hl=ko&ct=clnk&gl=kr
아키텍처를 알아야 앱 개발이 보인다 - 옥수환 저자
'안드로이드 공부 노트' 카테고리의 다른 글
[Android] 안드로이드 뷰 페이저2(ViewPager2)+탭 레이아웃(TabLayout) 예제를 통한 사용법 (0) | 2022.03.13 |
---|---|
[Android]안드로이드 매니페스트(Manifest)란? - 개념,역할 (0) | 2022.03.10 |
Android Jetpack - 4편 데이터 바인딩(Data Binding)이란? (0) | 2022.02.20 |
코루틴(Coroutine)이란? (0) | 2022.02.04 |
[Android] Context란? (0) | 2022.01.29 |