데이터 가져 오기 (특히 Firebase)를 처리하는 별도의 클래스가 있으며 일반적으로 여기에서 LiveData 개체를 반환하고 비동기 적으로 업데이트합니다. 이제 반환 된 데이터를 ViewModel에 저장하고 싶지만 문제는 해당 값을 얻으려면 데이터 가져 오기 클래스에서 반환 된 LiveData 개체를 관찰해야한다는 것입니다. 관찰 메서드에는 첫 번째 매개 변수로 LifecycleOwner 개체가 필요했지만 분명히 ViewModel 내부에는 해당 개체가 없으며 ViewModel 내부의 Activity / Fragment에 대한 참조를 유지하지 않아야한다는 것을 알고 있습니다. 어떻게해야합니까?
답변
Google 개발자 인 Jose Alcérreca 의이 블로그 게시물 에서는 ViewModel 이 View
(활동, 컨텍스트 등) 과 관련된 참조를 보유하지 않아야 하기 때문에이 경우 변환을 사용하는 것이 좋습니다 ( “저장소의 LiveData”단락 참조 ). 테스트합니다.
답변
에서 의 ViewModel의 문서
그러나 ViewModel 개체는 LiveData 개체와 같은 수명주기 인식 관찰 가능 항목의 변경 사항을 관찰해서는 안됩니다.
또 다른 방법은 데이터가 LiveData가 아닌 RxJava를 구현하는 것입니다. 그러면 수명주기를 인식하는 이점이 없습니다.
todo-mvvm-live-kotlin 의 Google 샘플에서는 ViewModel에서 LiveData 없이 콜백을 사용합니다.
라이프 사이클웨어라는 전체 아이디어를 준수하려면 Activity / Fragment에서 관찰 코드를 이동해야합니다. 그렇지 않으면 ViewModel에서 콜백 또는 RxJava를 사용할 수 있습니다.
또 다른 절충안은 MediatorLiveData (또는 Transformations)를 구현하고 ViewModel에서 관찰 (여기에 논리 입력)하는 것입니다. MediatorLiveData 관찰자는 Activity / Fragment에서 관찰되지 않는 한 트리거되지 않습니다 (변환과 동일). 우리가하는 일은 실제 작업이 ViewModel에서 실제로 수행되는 Activity / Fragment에 빈 관찰을 넣는 것입니다.
// ViewModel
fun start(id : Long) : LiveData<User>? {
val liveData = MediatorLiveData<User>()
liveData.addSource(dataSource.getById(id), Observer {
if (it != null) {
// put your logic here
}
})
}
// Activity/Fragment
viewModel.start(id)?.observe(this, Observer {
// blank observe here
})
추신 : 나는 ViewModels 및 LiveData : Patterns + AntiPatterns 를 읽었 으며 변환을 제안했습니다. LiveData가 관찰되지 않는 한 작동하지 않는다고 생각합니다 (아마도 Activity / Fragment에서 수행해야 함).
답변
라이프 사이클 소유자 인터페이스가 필요하지 않은 observeForever를 사용할 수 있고 viewmodel의 결과를 관찰 할 수 있다고 생각합니다.
답변
아키텍처 구성 요소와 함께 Kotlin 코 루틴을 사용합니다.
liveData
빌더 함수를 사용하여 함수를 호출 suspend
하여 결과를 LiveData
객체 로 제공 할 수 있습니다 .
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
블록에서 여러 값을 내보낼 수도 있습니다. 각 emit()
호출은 LiveData
값이 기본 스레드에 설정 될 때까지 블록 실행을 일시 중단합니다 .
val user: LiveData<Result> = liveData {
emit(Result.loading())
try {
emit(Result.success(fetchUser()))
} catch(ioException: Exception) {
emit(Result.error(ioException))
}
}
gradle 구성에서 androidx.lifecycle:lifecycle-livedata-ktx:2.2.0
이상을 사용하십시오 .
그것에 관한 기사 도 있습니다.
업데이트 : 또한 그것은 변경 가능 LiveData<YourData>
에 Dao
interface
. suspend
함수에 키워드 를 추가해야 합니다.
@Query("SELECT * FROM the_table")
suspend fun getAll(): List<YourData>
그리고 ViewModel
당신 은 다음과 같이 비동기 적으로 가져와야합니다.
viewModelScope.launch(Dispatchers.IO) {
allData = dao.getAll()
// It's also possible to sync other data here
}