728x90
Event.kt
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
ViweModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.anushka.roomdemo.db.Subscriber
import com.anushka.roomdemo.db.SubscriberRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class SubscriberViewModel(private val repository: SubscriberRepository) : ViewModel(){
val subscribers = repository.subscribers
private var isUpdateOrDelete = false
private lateinit var subscriberToUpdateOrDelete : Subscriber
val inputName = MutableLiveData<String>()
val inputEmail = MutableLiveData<String>()
val saveOrUpdateButtonText = MutableLiveData<String>()
val clearAllOrDeleteButtonText = MutableLiveData<String>()
private val statusMessage = MutableLiveData<Event<String>>()
val message : LiveData<Event<String>>
get() = statusMessage
init {
saveOrUpdateButtonText.value = "Save"
clearAllOrDeleteButtonText.value = "Clear All"
}
fun saveOrUpdate(){
if(isUpdateOrDelete){
subscriberToUpdateOrDelete.name = inputName.value!!
subscriberToUpdateOrDelete.email = inputEmail.value!!
update(subscriberToUpdateOrDelete)
}else {
val name = inputName.value!!
val email = inputEmail.value!!
insert(Subscriber(0, name, email))
inputName.value = ""
inputEmail.value = ""
}
}
fun clearAllOrDelete(){
if(isUpdateOrDelete){
delete(subscriberToUpdateOrDelete)
}else {
clearAll()
}
}
fun insert(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(subscriber)
withContext(Dispatchers.Main){
statusMessage.value = Event("Subscriber Inserted Successfully!")
}
}
fun update(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.update(subscriber)
withContext(Dispatchers.Main){
inputName.value = ""
inputEmail.value = ""
isUpdateOrDelete = false
saveOrUpdateButtonText.value = "Save"
clearAllOrDeleteButtonText.value = "Clear All"
statusMessage.value = Event("Subscriber Updated Successfully!")
}
}
fun delete(subscriber: Subscriber) = viewModelScope.launch(Dispatchers.IO) {
repository.delete(subscriber)
withContext(Dispatchers.Main){
inputName.value = ""
inputEmail.value = ""
isUpdateOrDelete = false
saveOrUpdateButtonText.value = "Save"
clearAllOrDeleteButtonText.value = "Clear All"
statusMessage.value = Event("Subscriber Deleted Successfully!")
}
}
fun clearAll() = viewModelScope.launch(Dispatchers.IO) {
repository.deleteAll()
withContext(Dispatchers.Main){
statusMessage.value = Event("All Subscribers Deleted Successfully!")
}
}
fun initUpdateAndDelete(subscriber: Subscriber){
inputName.value = subscriber.name
inputEmail.value = subscriber.email
isUpdateOrDelete = true
subscriberToUpdateOrDelete = subscriber
saveOrUpdateButtonText.value = "Update"
clearAllOrDeleteButtonText.value = "Delete"
}
}
MainActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.anushka.roomdemo.databinding.ActivityMainBinding
import com.anushka.roomdemo.db.Subscriber
import com.anushka.roomdemo.db.SubscriberDatabase
import com.anushka.roomdemo.db.SubscriberRepository
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var subscriberViewModel: SubscriberViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
val dao = SubscriberDatabase.getInstance(application).subscriberDAO
val repository = SubscriberRepository(dao)
val factory = SubscriberViewModelFactory(repository)
subscriberViewModel = ViewModelProvider(this,factory)[SubscriberViewModel::class.java]
binding.myViewModel = subscriberViewModel
binding.lifecycleOwner = this
initRecyclerView()
subscriberViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
}
})
}
private fun initRecyclerView(){
binding.subscriberRecyclerView.layoutManager = LinearLayoutManager(this)
displaySubscribersList()
}
private fun displaySubscribersList(){
subscriberViewModel.subscribers.observe(this, Observer {
Log.i("MYTAG",it.toString())
binding.subscriberRecyclerView.adapter = MyRecyclerViewAdapter(it,{selectedItem:Subscriber->listItemClicked(selectedItem)})
})
}
private fun listItemClicked(subscriber: Subscriber){
Toast.makeText(this,"selected name is ${subscriber.name}", Toast.LENGTH_LONG).show()
subscriberViewModel.initUpdateAndDelete(subscriber)
}
}
참고
https://yk-coding-letter.tistory.com/5
MVVM에서 ViewModel의 Event 전달하기(Event Wrapper)
MVVM Architecture에서 기본 개념 중 하나는 View는 ViewModel을 알지만, ViewModel은 View를 알지 못하게 하자는 것이다. 그로인해 ViewModel은 로직에 집중할 수 있게 된다. AAC ViewModel에서 작업이 끝나면 LiveData
yk-coding-letter.tistory.com
LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)
2021 Update: This guidance is deprecated in favor of the official guidelines.
medium.com
728x90
'안드로이드 > ViewModel' 카테고리의 다른 글
viewmodel에서 R.string 처리하기 (0) | 2023.03.10 |
---|---|
안드로이드 viewmodel 생성 방법 (0) | 2022.09.26 |