我想用不同的来源来使用同一个LiveData,一个来自API调用,是一个observable,一个来自数据库,是一个LiveData。一个来自API调用,是一个可观察的数据,一个来自数据库,是一个LiveData。我希望能够做这样的事情。
private LiveData<List<Items>> items = new MutableLiveData<>();
// this one comes from an API and it's an observable
public void onApiItemsSelected(String name) {
Disposable disposable = repository.getItemsFromApi(name)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(itemsList -> {
items.setValue(itemsList);
});
compositeDisposable.add(disposable);
}
// this one comes from the database and it's a livedata that I want to transform first
public void onDatabaseItemsSelected() {
items = Transformations.map(repository.getItemsFromdatabase(), itemsList -> {
List<Items> finalItemsList = new ArrayList<>();
for (Item item : itemsList) {
finalItemsList.add(itemsList.toSomething());
}
return finalItemsList;
});
}
问题是Transformation.map总是返回一个LiveData,而为了制作一个... items.setValue( itemsList) 项目需要是一个MutableLiveData。我试过用MediatorLiveData,但它调用了两个源,把所有东西都混在一起。这不是我所需要的。我需要一个源或者另一个源。这可能吗?
我想你可以把这个责任委托给你的存储库。
基本上,存储库处理了决定从哪个源获取数据的所有复杂问题(见下面的 JobRepository). 它暴露了一个rx Observable
至 ViewModel
(见 工作查看模型). 然后,ViewModel要做的就是更新该视图的 LiveData
:
private val presentation: MutableLiveData<Presentation> = MutableLiveData()
fun bind() {
jobRepository.getJobs(true)
.subscribeOn(Schedulers.io())
.subscribe { resource: Resource<List<JobWithRelations>> ->
when (resource) {
// commenting some parts for brevity ...
is Resource.ResourceFound -> {
presentation.postValue(Presentation(getApplication(), resource.data!!))
}
// ...
}
}.addTo(compositeDisposable)
}
管理多个数据源是很复杂的。在架构中涉及的许多方面中,需要牢记的事情包括。
一个可以帮助你的库是Dropbox的 商店. 有了它,你可以像下面的例子一样,从他们的文档中建立你的数据源。
StoreBuilder
.from(
fetcher = nonFlowValueFetcher { api.fetchSubreddit(it, "10").data.children.map(::toPosts) },
sourceOfTruth = SourceOfTrue.from(
reader = db.postDao()::loadPosts,
writer = db.postDao()::insertPosts,
delete = db.postDao()::clearFeed,
deleteAll = db.postDao()::clearAllFeeds
)
).build()
然后在你的ViewModel中获取数据,
private val presentation: MutableLiveData<Presentation> = MutableLiveData()
lifecycleScope.launchWhenStarted {
store.stream(StoreRequest.cached(key = key, refresh=true)).collect { response ->
when(response) {
// commenting some parts for brevity ...
is StoreResponse.Data -> {
presentation.postValue(response.value)
}
// ...
}
}
}
我不确定这是最好的做法,但我认为可以做到这一点。
public void onDatabaseItemsSelected() {
items.value = repository.getItemsFromdatabase().value;
};
语法可能并不准确,因为我对java知之甚少,我主要做的是kotlin。但问题是:当用户点击Api时,让你的onApiItemsSelected()运行,这将会设置ApiItemsSelected的值。物品,当用户点击数据库时,使 onDatabaseItemsSelected() 运行,所以它将取代 物品 结果的值 repository.getItemsFromDatabase()