[Android jetpack room 예제 : Todo - (1)]
Android jetpack room 을 활용하여 할일(Todo) 예제를 확인해보았는데요
이번에는 jetpack ViewModel 및 LiveData 에 대해서 알아보고,
Todo 예제를 이어서 jetpack ViewModel-LiveData 을 적용하려고합니다.
1. jetpack ViewModel
ViewModel 클래스는 수명 주기를 고려하여 UI 관련 데이터를 저장하고 관리하도록 설계되었습니다.
UI 관련 데이터를 저장하고 관리한다는 건 바로 알겠는데 수명 주기를 고려한다는 것은 조금 더 알아보겠습니다.
아래 그림은 activity가 생성된 후 회전 시키고 종료 될 때까지의 수명주기 상태를 보여줍니다
Activity 회전될 때 re-onCreate 과정에서 ViewModel Scope 는 계속 유지가 되고 App 이 종료되서야 clear 되는 것을 볼 수 있습니다.
그렇다면 수명주기를 고려한다는 것은 액티비티가 중간에 재생성되는 것에 개의치 않고 보존된다.
즉, 기존에 보관되있던 View 관련 데이터를 계속해서 사용할 수 있다는 것을 의미합니다.
Observer에게 데이터 변경에 대한 알림을 보내는 클래스입니다.
계속해서 데이터를 관찰하고 업데이트되기 때문에 UI 와 데이터간에 일치성을 가진다는 장점을 가지고 있습니다.
3. jetpack ViewModel-LiveData 활용
이전에 사용했던 Todo 예제를 계속해서 이어가려고 합니다.
중간중간 생략되는 부분들도 있을거라서 소스를 받고 함께 보는걸 추천드립니다:)
아래 두가지 포인트를 가지고 시작해봅시다.
- room 의 데이터베이스를 ViewModel 에서 관리하게 할 것
- room 에 저장되는 데이터(List<Todo>) 를 LiveData 로 처리
♣ ViewModel
데이터를 보관하고 관리하기 위한 class MainViewModel 를 만들고 todoDataBase 를 보관해줍니다. View 에서는 getDao() 를 통해 room 에 접근 할 수 있을 것입니다.
class MainViewModel(application: Application) : AndroidViewModel(application) {
private var todoDataBase = TodoDataBase.getInstance(application)
fun getDao(): TodoDao? {
return todoDataBase?.todoDao()
}
}
MainActivity 에 MainViewModel 을 사용하기 위해 아래와 같이 불러올 수 있습니다.
// Load mainViewModel
val mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
♣ LiveData
기존에 사용하였던 List<Todo> 를 LiveData 로 변경해줍니다.
@Query("SELECT * FROM todo")
fun getAll(): LiveData<List<Todo>>
아래와 같이 LiveData 객체와 Observer 객체를 연결해주고, 데이터 변경에 따른 동작을 정의해줍니다.
mainViewModel.getDao()?.getAll()?.observe(this, Observer {
todoAdapter = TodoAdapter(ArrayList(it), mainViewModel)
rvResult.adapter = todoAdapter
})
♣ MainActivity 전체소스
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Load mainViewModel
val mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
// UI Initialize
val etTodo = findViewById<EditText>(R.id.etTodo)
val btnAdd = findViewById<Button>(R.id.btnAdd)
val rvResult = findViewById<RecyclerView>(R.id.rvResult)
val btnDeleteAll = findViewById<Button>(R.id.btnDeleteAll)
val btnDelete = findViewById<Button>(R.id.btnDelete)
var todoAdapter = TodoAdapter(ArrayList(), mainViewModel)
val viewManager = LinearLayoutManager(this)
rvResult.apply {
setHasFixedSize(true)
layoutManager = viewManager
adapter = todoAdapter
}
// Use LiveData-ViewModel
mainViewModel.getDao()?.getAll()?.observe(this, Observer {
todoAdapter = TodoAdapter(ArrayList(it), mainViewModel)
rvResult.adapter = todoAdapter
})
// UI Listener
btnAdd.setOnClickListener {
if (etTodo.text.toString().isNotEmpty()) {
val todo = Todo(etTodo.text.toString(), false)
mainViewModel.getDao()?.insert(todo)
etTodo.setText("")
}
}
btnDeleteAll.setOnClickListener {
mainViewModel.getDao()?.deleteAll()
}
btnDelete.setOnClickListener {
val todo = todoAdapter.getSelectedItem()
todo?.run {
mainViewModel.getDao()?.delete(this)
}
}
}
}
참고자료
https://developer.android.com/topic/libraries/architecture/viewmodel
https://developer.android.com/topic/libraries/architecture/livedata
0 comments: