【问题标题】:Android mediator live data combine 2 live data into one stream and one triggerAndroid mediator live data 将 2 个 live data 合并为一个 stream 和一个 trigger
【发布时间】:2020-03-29 18:55:17
【问题描述】:

我有 2 个实时数据,我将它们作为源添加到中介实时数据中,我从视图模型中公开它以供片段观察。

当任何一个实时数据发生变化时,它会触发中介实时数据的 onChanged 方法,这意味着我的观察者被触发了两次,我想要将两者结合起来并观察一个只触发一次的流,有什么东西吗我失踪了,或者我需要为此推出自己的方法吗?目前我这样做,触发两次

为简洁起见删除了一些代码

public CardViewModel(@NonNull Application application , int clicks, String[] cardArgs){
    sentenceRepository = new SentenceRepository(application);
    cards = Transformations.switchMap(search, mySearch -> sentenceRepository.searchLiveCardListByWordTypeAndWordDescriptionAndSearchWord(cardArgs[0],cardArgs[1],mySearch));
    groupRepository = new GroupRepository(application);
    groups = groupRepository.getGroupsByWordDescriptionAndWordType(cardArgs[0],cardArgs[1]);
    sentencesAndGroups = new MediatorLiveData<>();

    sentencesAndGroups.addSource(cards, sentences -> {
        Log.d(TAG,"addSource cards");
        sentencesAndGroups.setValue(combineLatest(sentences, groups.getValue()));
    });

    sentencesAndGroups.addSource(groups, groupsWithSentences -> {
        Log.d(TAG,"addSource groups");
        sentencesAndGroups.setValue(combineLatest(cards.getValue(), groupsWithSentences));
    });

}

private List<Visitable> combineLatest(List<Sentence> sentenceList, List<GroupsWithSentences> groupsWithSentences) {
    List<Visitable> visitableList = new ArrayList<>();
    if (sentenceList != null){
        visitableList.addAll(sentenceList);
    }
    if (groupsWithSentences != null){
        visitableList.addAll(groupsWithSentences);
    }
    return visitableList;
}

有什么帮助吗?

【问题讨论】:

    标签: android android-livedata android-viewmodel mediatorlivedata


    【解决方案1】:

    您可以使用BiFunction。在我的项目中,我有一个包含以下内容的类:

    public class MultipleLiveDataTransformation {
        @MainThread
        public static <X, Y, O> LiveData<O> biMap(LiveData<X> data1, LiveData<Y> data2, final BiFunction<X, Y, O> biFun) {
            final MediatorLiveData<O> result = new MediatorLiveData<>();
            result.addSource(data1, x -> result.setValue(biFun.apply(x, data2.getValue())));
            result.addSource(data2, y -> result.setValue(biFun.apply(data1.getValue(), y)));
    
            return result;
        }
    }
    

    你可以这样使用它:

    public LiveData<Visitable> getVisitables() {
        return MultipleLiveDataTransformation.biMap(groups, sentences, (gro, sen) -> {
            List<Visitable> visitableList = new ArrayList<>();
            if (gro != null) {
                visitableList.addAll(gro);
            }
            if (sen != null) {
                visitableList.addAll(sen);
            }
            return visitableList;
        });
    }
    

    我不完全了解您拥有哪些列表以及您想要观察什么。我在这里给出的示例可以观察到两个LiveData 对象并在其中一个需要更新时触发。它将始终为您提供Visitable 对象的最新版本。

    如果我不明白这个问题,你能解释一下LiveData对象需要组合什么,结果需要是什么?

    如果需要在MultipleDataTransformation 中观察到一个额外的LiveData 对象,则可以创建一个triMap。

    编辑: 你可以试试这个:

    public LiveData<Visitable> getVisitables() {
        return MultipleLiveDataTransformation.biMap(groups, sentences, (gro, sen) -> {
            List<Visitable> visitableList = new ArrayList<>();
            if (gro != null && !gro.isEmpty() && sen != null && !sen.isEmpty()) {
                visitableList.addAll(gro);
                visitableList.addAll(sen);
            }
            return visitableList;
        });
    }
    

    【讨论】:

    • 这里的问题是它每次最新的实时数据发出一个值时都会更新,所以它总是会触发两次,因为实时数据永远不会同时完成,我想要的可能是一个检查查看一个是否已完成,然后超时告诉实时数据是否应该完成并发出一个值或等待其他实时数据完成,因为我只想要一个流,如油门在 rxjava 上工作
    • 那么我认为这不适合您的问题。这将触发,例如组或句子被更新。如果groups 或sentences 为空,您可以做的是在biMap 中返回一个空列表。如果它们都被填满,您可以将它们组合起来并返回完整的列表。您可以调用 getVisitables() 并在更新前检查列表是否为空。
    • 嗯,这个主意不错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多