1
Android 프로젝트에서 Room + LiveData를 사용하고 있습니다. Google Blueprints에 따라 애플리케이션의 데이터 레이어를 구현했습니다. 내 EventRepository에서 호출하고 있습니다ID로 항목 가져 오기
@Query("SELECT * FROM events WHERE id=:arg0")
fun loadSingle(id: String): LiveData<Event>
:처럼 내 다오 모양을
이입니다
fun loadSingle(eventId: String): LiveData<RequestReader<Event>> {
return object: NetworkManager<Event, Event>(appExecutors!!) {
override fun loadLocal(): LiveData<Event> {
val item = eventLocal!!.loadSingle("Title 1")
Crashlytics.log(Log.VERBOSE, TAG, "loadFromServer::loadLocal=$item")
return item
}
override fun isUpdateForced(data: Event?): Boolean {
Crashlytics.log(Log.VERBOSE, TAG, "loadFromServer::isUpdateForced")
return data == null || requestTimeout.isAllowed(UNDEFINED_KEY.toString())
}
override fun makeRequest(): LiveData<ApiResponse<Event>> {
Crashlytics.log(Log.VERBOSE, TAG, "loadFromServer::makeRequest")
return Database.createService(EventRemote::class.java).load(eventId)
}
override fun onSuccess(item: Event) {
eventLocal?.save(item)
}
override fun onFail() {
Crashlytics.log(Log.VERBOSE, TAG, "loadFromServer::onFail")
requestTimeout.reset(UNDEFINED_KEY.toString())
}
}.liveData
}
네트워크 매니저 클래스 (
here에서 "촬영"된)입니다
:
abstract class NetworkManager<ResultType, RequestType> @MainThread constructor(val appExecutors: AppExecutors) {
companion object {
private val TAG = "TAG_NETWORK_MANAGER"
}
val liveData: MediatorLiveData<RequestReader<ResultType>> = MediatorLiveData()
init {
liveData.value = RequestReader.loading(null)
val localSource: LiveData<ResultType> = loadLocal()
Log.d(TAG, "before add::localSource=${localSource.value}")
liveData.addSource(localSource, { data ->
Log.d(TAG, "data=$data")
liveData.removeSource(localSource)
if (isUpdateForced(data)) {
loadRemote(localSource)
} else {
liveData.addSource(localSource, { reusedData -> liveData.value = RequestReader.success(reusedData)})
}
})
}
private fun loadRemote(localSource: LiveData<ResultType>) {
val remoteSource = makeRequest()
liveData.addSource(localSource, {
liveData.value = RequestReader.success(it)
})
liveData.addSource(remoteSource) { response ->
liveData.removeSource(localSource)
liveData.removeSource(remoteSource)
if (response!!.isSuccessful) {
appExecutors.diskIO.execute {
onSuccess(processResponse(response))
appExecutors.mainThread.execute {
liveData.addSource(localSource, {
liveData.value = RequestReader.success(it)
})
}
}
} else {
onFail()
liveData.addSource(localSource, {
liveData.value = RequestReader.error("Error: ${response.errorMessage}", it)
})
}
}
}
@MainThread
protected abstract fun loadLocal(): LiveData<ResultType>
@MainThread
protected abstract fun isUpdateForced(data: ResultType?): Boolean
@MainThread
protected abstract fun makeRequest(): LiveData<ApiResponse<RequestType>>
@WorkerThread
protected abstract fun onSuccess(item: RequestType)
@MainThread
protected abstract fun onFail()
@WorkerThread
protected fun processResponse(response: ApiResponse<RequestType>): RequestType {
return response.body!!
}
}
그리고 난 오의 ViewModel 내 LiveData를 얻을 :
open class EventSingleViewModel: ViewModel(), RepositoryComponent.Injectable {
companion object {
private val TAG = "TAG_EVENT_SINGLE_VIEW_MODEL"
}
@Inject lateinit var eventRepository: EventRepository
var eventSingle: LiveData<RequestReader<Event>>? = null
override fun inject(repositoryComponent: RepositoryComponent) {
repositoryComponent.inject(this)
eventSingle = MutableLiveData<RequestReader<Event>>()
}
fun load(eventId: String) {
Crashlytics.log(Log.VERBOSE, TAG, "starts to loadList::eventId=$eventId")
eventSingle = eventRepository.loadSingle(eventId)
}
}
문제입니다. 위와 같은 방법으로 이벤트 목록을 얻고 있습니다 (이 이벤트는 이미 데이터베이스에 있음). 작동하지 않습니다. localSource.value가 null 인 것을 발견했습니다 (NetworkManager). 어쩌면 내 쿼리가 나쁘거나 뭔가 다른 것일 수 있습니다.
미리 감사드립니다.