1

Ich benutze Room + LiveData in meinem Android-Projekt. Nach Google Blueprints habe ich die Datenschicht meiner Anwendung implementiert. DieseErhalte Artikel nach ID in Raum

ist, wie mein Dao wie folgt aussieht:

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

ich es von meinem EventRepository bin Aufruf:

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 
    } 

Wo Networkmanager-Klasse (wurde von here "genommen" worden) :

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!! 
    } 
} 

Und nachdem erwarte ich t o bekommen meine Livedata in Ansichtsmodell:

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) 
    } 

} 

Das Problem. Ich bin eine Liste von Ereignissen immer auf die gleiche Weise (es funktioniert!) Ich habe oben beschrieben, jedoch mit einem einzigen Ereignisse (diese Veranstaltung ist bereits in der Datenbank) es funktioniert nicht. Ich habe herausgefunden, dass localSource.value null ist (in NetworkManager). Vielleicht ist meine Frage schlecht oder etwas anderes.

Vielen Dank im Voraus.

Antwort

1

prüft erneut Ihre DAO Implementierung, das Argument ist bei beiden gleich sein, die Funktionsparameter und die Anmerkung arg. diese

Wechsel:

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

An:

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