Android mediator实时数据将2个实时数据合并为一个流和一个触发器

Android mediator实时数据将2个实时数据合并为一个流和一个触发器,android,android-livedata,android-viewmodel,mediatorlivedata,Android,Android Livedata,Android Viewmodel,Mediatorlivedata,我有2个实时数据,我将它们作为源添加到中介实时数据中,我从视图模型中公开这些数据,以供片段观察 当任何一个实时数据更改时,它会触发中介实时数据的onChanged方法,这意味着我的观察者会被触发两次,我想要的是将两者结合起来,只观察一个只触发一次的流,我是否缺少什么,或者我需要为此使用自己的方法?目前我这样做,会触发两次 为了简洁起见删除了一些代码 public CardViewModel(@NonNull Application application , int clicks, String

我有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;
}
公共CardViewModel(@NonNull应用程序,int单击,字符串[]cardArgs){ sentenceRepository=新的sentenceRepository(应用程序); cards=Transformations.switchMap(搜索,mySearch->sentenceRepository.SearchLiveCardListByWordTypeandWordDescription和SearchWord(cardArgs[0],cardArgs[1],mySearch)); groupRepository=新的groupRepository(应用程序); groups=groupRepository.getgroupsbyworddescription和wordtype(cardArgs[0],cardArgs[1]); sentencesAndGroups=新的MediatorLiveData(); 句子和组。添加来源(卡片、句子->{ 日志d(标签“添加源卡”); setValue(combineTest(句子,groups.getValue()); }); 语句和组。添加源(组、组和句子->{ Log.d(标记“addSource组”); setValue(组合测试(cards.getValue(),groupswith句子)); }); } 私有列表组合测试(列表句子列表、列表组和句子){ List visitableList=新建ArrayList(); if(语句列表!=null){ visitableList.addAll(句子列表); } if(groupswith句子!=null){ visitableList.addAll(Groupswith句子); } 返回可访问列表; }
有什么帮助吗?

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

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

这里的问题是,每次最新的实时数据发出值时,它都会更新,因此它总是会触发两次,因为实时数据永远不会同时完成,我想要的可能是检查一个是否完成,然后超时,告诉实时数据它是否应该完成并发出一个值,或者等待其他实时数据完成,因为我只希望一个流(如throttle)在RxJavaServer上工作,那么我认为这不适合您的问题。这将在组或句子更新时触发。如果
句子
为空,您可以在biMap中返回一个空列表。如果它们都已填写,则可以将它们合并并返回完整列表。在更新之前,可以调用getVisitables()并检查列表是否为空。yh这主意不错
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;
    });
}
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;
    });
}