在 Room 中通过 id 获取项目

Get item by id in Room

我在 Android 项目中使用 Room + LiveData。按照 Google 蓝图,我已经实现了我的应用程序的数据层。

我的道是这样的:

@Query("SELECT * FROM events WHERE id=:arg0")
    fun loadSingle(id: String): LiveData<Event>

我从我的 EventRepository 调用它:

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
    }

NetworkManager class 在哪里(从 here "taken"):

    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 为空(在 NetworkManager 中)。也许我的查询不好或者.. 其他原因。

再次检查您的 DAO 实现,函数参数和注释 arg 中的参数必须相同。

改变这个:

@Query("SELECT * FROM events WHERE id=:arg0")
fun loadSingle(id: String): LiveData<Event>

收件人:

@Query("SELECT * FROM events WHERE id=:id ")
fun loadSingle(id: String): LiveData<Event>