본문 바로가기

개발 일기/Android

[Kotlin] 간단 메모장 만들기3 #LiveData #ViewModel

LiveData와 ViewModel을 사용해서 저장되면 바로 데이터가 바뀌게 변경한다.

 

DiaryDao.kt

 

@Dao
interface DiaryDao {

    @Query("SELECT * FROM diary")
    fun getAll(): LiveData<List<Diary>>
    
}

 

기존에 작성했던 Dao에서 LiveData<>를 추가했다.

 

그리고 Repository를 작성한다. 여기서 간단하게 데이터를 뿌려주는 역할을 한다.

 

Repository.kt

 

class Repository (application: Application){

    private val database = AppDatabase.getInstance(application)!!
    private val diaryDao = database.diaryDao()
    private val diarys: LiveData<List<Diary>> = diaryDao.getAll()

    fun getAll(): LiveData<List<Diary>> {
        return diarys
    }

    fun insert(diary: Diary) {
        try {
            val thread = Thread(Runnable {
                diaryDao.insert(diary) })
            thread.start()
        } catch (e: Exception) { }
    }

    fun delete(diary: Diary) {
        try {
            val thread = Thread(Runnable {
                diaryDao.delete(diary)
            })
            thread.start()
        } catch (e: Exception) { }
    }
}

 

Room은 메인 thred에서 돌리면 오류가 나기 때문에 따로 thred를 만들어서 사용해야 한다.

AsyncTask와 kotlin에서 사용하는 코루틴 등... 몇 가지 방법이 있는데 여기서는 많은 데이터를 가져오는 게 아니기 때문에 간단하게 thred를 사용해 가져왔다.

 

이 데이터를 뷰모델과 합쳐서 fragment에 보여줄 것이다.

 

MainFragment.kt

 

class MainFragment : Fragment() {

    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.main_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
        val title = MainFragment_TextView_title
        val content = MainFragment_TextView_content
        viewModel.getAll().observe(viewLifecycleOwner, Observer {
            title.text = it[it.size-1].title
            content.text = it[it.size-1].content
        })
    }
    
}

 

기존 예제에서 알려주는 방식과 몇 가지 차이점이 있다.

viewModel = ViewModelProvider(this).get(MainViewModel::class.java)

이제는 ViewModelProvider를 사용하기 때문에 이걸로 바꿔주어야 한다.

 

그리고 계속해서 Cannot create an instance of class 이런 오류가 났다.

대부분 설정은 다 맞게 했는데 오류가 하두나서 ViewModel에 문제가 있지 않을까 해서 다른 방식을 찾아봤다.

 

MainViewModel.kt

 

class MainViewModel (application: Application): AndroidViewModel(application) {
    private val repository = DiaryRepository(application)
    private val diarys = repository.getAll()

    fun getAll(): LiveData<List<Diary>> {
        return this.diarys
    }

    fun insert(diary: Diary) {
        repository.insert(diary)
    }

    fun delete(diary: Diary) {
        repository.delete(diary)
    }
}

 

기존 상속받던 ViewModel을 AndroidViewModel로 바꾸고 application을 넣어주었다.

이렇게 하니까 오류가 말끔히 사라지고 LiveData로 바로바로 데이터가 바뀌는 것을 볼 수 있다.

 

 

작동 중~~