LiveData有两个来源?

问题描述 投票:0回答:1

我想用不同的来源来使用同一个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,但它调用了两个源,把所有东西都混在一起。这不是我所需要的。我需要一个源或者另一个源。这可能吗?

android android-livedata android-architecture-components mutablelivedata mediatorlivedata
1个回答
1
投票

我想你可以把这个责任委托给你的存储库。

例如,请看这个 开源项目 及相关 文章 的更多信息。

基本上,存储库处理了决定从哪个源获取数据的所有复杂问题(见下面的 JobRepository). 它暴露了一个rx ObservableViewModel (见 工作查看模型). 然后,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)
    }

管理多个数据源是很复杂的。在架构中涉及的许多方面中,需要牢记的事情包括。

  • 内存缓存到期战略
  • db缓存的策略,例如,当用户离线时的策略
  • API调用的节流和重试。
  • 当新数据来自网络时,更新内存缓存或数据库的策略。

一个可以帮助你的库是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)
        }
        // ...
    }
  }
}

0
投票

我不确定这是最好的做法,但我认为可以做到这一点。


public void onDatabaseItemsSelected() {
items.value = repository.getItemsFromdatabase().value;
};

语法可能并不准确,因为我对java知之甚少,我主要做的是kotlin。但问题是:当用户点击Api时,让你的onApiItemsSelected()运行,这将会设置ApiItemsSelected的值。物品,当用户点击数据库时,使 onDatabaseItemsSelected() 运行,所以它将取代 物品 结果的值 repository.getItemsFromDatabase()

© www.soinside.com 2019 - 2024. All rights reserved.