繁体   English   中英

Java Android LiveData 调用依赖于其他 LiveData 的 Room 查询

[英]Java Android LiveData calls Room query dependent on other LiveData

更新:::

我已经更新了这个问题,以包含其他同样需要的 LiveData 演示:所以我们有 userLD,我们需要它的值来获取goalWeeklyLD,我们需要goalWeeklyLD 值来获取剩余的 4 个 LiveData 值,因为它们来自 Room 查询在查询中使用goalWeekly.dateproperties

:::::

我遇到了一个问题,我有一个片段必须填充 LiveData,该片段使用依赖于另一个 LiveData 值的查询。 当我的实时数据依赖于其他结果时,如何让我的实时数据正常工作?

不使用 Transitions.map() 视图模型会抛出错误,因为其他实时数据的值仍然为空。 使用视图模型中的 Transitions.map() 活动观察者会抛出错误,因为 LiveData 仍然为空。

我可能会通过使用一个非常大的嵌套查询来在一个自定义 DTO 中返回我需要的所有内容来欺骗我的方式。 但我宁愿了解这里发生了什么以及如何正确处理这种情况。

希望一些代码可以说明这一点

活动:

public class SomeFragment extends Fragment {

public static SomeFragment newInstance() {
    return new SomeFragment();
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    someViewModel = ViewModelProviders.of(this).get(SomeViewModel.class);


    //getting user details from previous activity
    Intent intent = getActivity().getIntent();
    if (intent != null){
        if (intent.hasExtra(USER_ID)){
            user = new User(intent.getStringExtra(USERNAME));
            user.setId(intent.getLongExtra(USER_ID,0));
            someViewModel.setUserLD(user);
        }
    }


    someViewModel.getUserLD().observe(this, new Observer<User>() {
        @Override
        public void onChanged(@Nullable User userVal) {
            user = userVal;
        }
    });
    someViewModel.getGoalWeeklyLD().observe(this, new Observer<User>() {
        @Override
        public void onChanged(@Nullable User userVal) {
            user = userVal;
        }
    });
    //the below Observer calls throw an error because LiveData is null. makes sense.
    //but how can i say "don't try and observe these until the transition.map has ran (because then it wont be null after if my understanding is right)" or something to that effect
    someViewModel.getFirstLD(user.getId()).observe(this, new Observer<XObject>() {
        @Override
        public void onChanged(@Nullable Grades avgSportGradeVal) {
            //Update UI
        }
    });
    someViewModel.getSecondLD(user.getId()).observe(this, new Observer<XObject>() {
        @Override
        public void onChanged(@Nullable Grades avgBoulderGradeVal) {
            // Update UI
        }
    });
    someViewModel.getThriLD(user.getId()).observe(this, new Observer<XObject>() {
        @Override
        public void onChanged(@Nullable Grades avgBoulderGradeVal) {
            // Update UI
        }
    });
    someViewModel.getFourthLD(user.getId()).observe(this, new Observer<XObject>() {
        @Override
        public void onChanged(@Nullable Grades avgBoulderGradeVal) {
            // Update UI
        }
    });

}}

视图模型:

public class SomeViewModel extends AndroidViewModel {
DaoRepository daoRepository;

MutableLiveData<User> userLD;
LiveData<XObject> firstLD;
LiveData<XObject> secondLD;
LiveData<XObject> thirdLD;
LiveData<XObject> fourthLD;



public MutableLiveData<User> getUserLD() {
    return userLD;
}
public void setUserLD(User user){
    userLD.setValue(user);
}

public LiveData<XObject> getFirstLD(long userId) {
    return goalWeeklyLD;
}
public LiveData<XObject> getSecondLD(long userId) {
    return goalWeeklyLD;
}
public LiveData<XObject> getThirdLD(long userId) {
    return goalWeeklyLD;
}
public LiveData<XObject> getForthLD(long userId) {
    return goalWeeklyLD;
}


public SomeViewModel(@NonNull Application application) {
    super(application);
    daoRepository = new DaoRepository(application);
    userLD = new MutableLiveData<>();


    //so the first LiveData waits for the user to be populated before getting its LiveData becasue we need the userId for our Room query to run
    firstLD = Transformations.map(userLD, user -> daoRepository.getMostRecentGoalWeekly(user.getId()).getValue());

    //the remaining live data uses values from the first...
    setupOtherTransformMaps(userLD.getValue())
}

public void setupOtherTransformMaps(long userId) {
    //the secondLD, thirdLD and fourthLD all depends on values from the first (in runs a query that uses its dateExpired)
    secondLD = Transformations.map(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()).getValue());
    thirdLD = Transformations.map(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()).getValue());
    fourthLD = Transformations.map(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()).getValue());
}}

值得庆幸的是,谷歌很聪明,并创建了一个组件,它允许您将可变数量的 LiveData 组合成一个 LiveData,并且仅在您选择这样做时才发出事件!

这称为 MediatorLiveData。

不过,在您的情况下,您只需要将 1 个 LiveData ( userLD ) userLD到另一个 LiveData 中,每次userLd具有新值时都会发出。

因此,您可以使用预定义的 MediatorLiveData 来执行此操作,特别是Transformations.switchMap

firstLD = Transformations.switchMap(userLD, user -> daoRepository.getMostRecentGoalWeekly(user.getId()));


编辑:是的,您似乎需要将这些 LiveData 彼此分开公开,但它们都取决于要执行的第一个查询。

所以,你需要更换Transformations.map { ...getValue()Transformations.switchMap ,你会好到哪里去。

public SomeViewModel(@NonNull Application application) {
    super(application);
    CustomApplication app = (CustomApplication) application;
    daoRepository = app.daoRepository();
    userLD = new MutableLiveData<>();

    firstLD = Transformations.switchMap(userLD, user -> daoRepository.getMostRecentGoalWeekly(user.getId()));

    secondLD = Transformations.switchMap(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()));
    thirdLD = Transformations.switchMap(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()));
    fourthLD = Transformations.switchMap(firstLD, first ->
            daoRepository.getAvgGradeRouteInPeriod(userId, first.getDateCreated(),first.getDateExpires()));

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM