【问题标题】:One LiveData returns null一个 LiveData 返回 null
【发布时间】:2021-03-14 03:19:07
【问题描述】:

我一直在尝试将两个实时数据结合起来显示在一项活动中。 我有表 Item、ItemMoto 和 ItemFavourite。当从存储在 Item 或 ItemMoto 中的产品中将产品添加到收藏夹时,它会保存 id、itemi、...

我使用这个库 livedata-combineutil-java 来组合来自 Item 和 ItemMoto 的结果。我试图将它们从 View Module 组合起来,但我没有得到结果。这是我在 Fragment 中的做法。

        LiveData<Pair<Resource<List<Item>>, Resource<List<ItemMoto>>>> news =
     combine(favouriteViewModel.getItemFavouriteData(), favouriteViewModelMoto.getItemFavouriteData(),
            (favorite, favoriteMoto) -> { 
         return Pair.create(favorite, favoriteMoto);
            });

    if (news != null) {
        news.observe(this, listResource -> {
            if (listResource != null) {

                switch (listResource.first.status) {
                    case LOADING:
                        // Loading State
                        // Data are from Local DB
                        if (listResource.first.data != null) {
                            //fadeIn Animation
                            fadeIn(binding.get().getRoot());
                            // Update the data
                            replaceDataItems(listResource.first.data, listResource.second.data);
                        }
                        break;
                    case SUCCESS:
                        // Success State
                        // Data are from Server
                        if (listResource.first.data != null) {
                            // Update the data
                            replaceDataItems(listResource.first.data, listResource.second.data);
                        }
                        favouriteViewModel.setLoadingState(false);

                        break;
                    case ERROR:
                        // Error State
                        favouriteViewModel.setLoadingState(false);
                        break;
                    default:
                        // Default
                        break;
                }
            } else {

                // Init Object or Empty Data

                if (favouriteViewModel.offset > 1) {
                    // No more data for this list
                    // So, Block all future loading
                    favouriteViewModel.forceEndLoading = true;
                }

            }

        });
    }

当我检查时:

 Log.d("favourite moto live", favouriteViewModelMoto.getItemFavouriteData().toString());
 
 Log.d("favourite  live", favouriteViewModel.getItemFavouriteData().toString());

我得到了结果,但 listResource.second.data 返回 null。

这里是资源文件的链接:

https://pastebin.com/ZGtBzLV0

更新:

最初,Item 和 ItemMoto 具有自己的 Activity 和 Fragment 以及自己的 LiveData。 我正在使用 ROOM 和 PHP 从服务器检索数据。

对于项目:

  @Query("SELECT prd.* FROM Item prd, ItemFavourite fp WHERE prd.id = 
  fp.itemId order by fp.sorting ")
   LiveData<List<Item>> getAllFavouriteProducts();

对于 ItemMoto:

  @Query("SELECT prd.* FROM ItemMoto prd, ItemFavourite fp WHERE prd.id =  
  fp.itemId order by fp.sorting ")
   LiveData<List<ItemMoto>> getAllFavouriteProducts();

视图模型

package com.panaceasoft.psbuyandsell.viewmodel.item;

import android.util.Log;
import androidx.core.util.Pair;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Transformations;

import com.panaceasoft.psbuyandsell.Config;
import com.panaceasoft.psbuyandsell.repository.item.ItemMotoRepository;
import com.panaceasoft.psbuyandsell.repository.item.ItemRepository;
import com.panaceasoft.psbuyandsell.utils.AbsentLiveData;
import com.panaceasoft.psbuyandsell.utils.Utils;
import com.panaceasoft.psbuyandsell.viewmodel.common.PSViewModel;
import com.panaceasoft.psbuyandsell.viewobject.Item;
import com.panaceasoft.psbuyandsell.viewobject.ItemMoto;
 import com.panaceasoft.psbuyandsell.viewobject.common.Resource;

import java.util.List;

import javax.inject.Inject;

import static   
com.zhuinden.livedatacombineutiljava.LiveDataCombineUtil.combine;

public class FavouriteViewModel extends PSViewModel {
private final LiveData<Resource<Boolean>> sendFavouritePostData;


private MutableLiveData<FavouriteViewModel.TmpDataHolder> 
sendFavouriteDataPostObj = new MutableLiveData<>();
private LiveData<Resource<List<Item>>> itemFavouriteData;
private LiveData<Resource<List<ItemMoto>>> itemFavouriteDataMoto;
private MutableLiveData<FavouriteViewModel.TmpDataHolder>  
itemFavouriteListObj = new MutableLiveData<>();
private MutableLiveData<FavouriteMotoViewModel.TmpDataHolder> 
itemFavouriteListObjMoto = new MutableLiveData<>();

private final LiveData<Resource<Boolean>> nextPageFavouriteLoadingData;
private MutableLiveData<FavouriteViewModel.TmpDataHolder> nextPageLoadingFavouriteObj = new MutableLiveData<>();

@Inject
FavouriteViewModel(ItemRepository itemRepository, ItemMotoRepository itemMotoRepository) {


    sendFavouritePostData = Transformations.switchMap(sendFavouriteDataPostObj, obj -> {

        if (obj == null) {
            return AbsentLiveData.create();
        }
        return itemRepository.uploadFavouritePostToServer(obj.itemId, obj.userId);
    });

    itemFavouriteData = Transformations.switchMap(itemFavouriteListObj, obj -> {
        if (obj == null) {
            return AbsentLiveData.create();
        }
        Utils.psLog("itemFavouriteData");
        return itemRepository.getFavouriteList(Config.API_KEY, obj.userId, obj.offset);
    });

 //Moto
    itemFavouriteDataMoto = 
 Transformations.switchMap(itemFavouriteListObjMoto, obj -> {
        if (obj == null) {
            return AbsentLiveData.create();
        }
        Utils.psLog("itemFavouriteData");
        return itemMotoRepository.getFavouriteList(Config.API_KEY,  
  obj.userId, obj.offset);
    });

    nextPageFavouriteLoadingData = Transformations.switchMap(nextPageLoadingFavouriteObj, obj -> {
        if (obj == null) {
            return AbsentLiveData.create();
        }
        Utils.psLog("nextPageFavouriteLoadingData");
        return itemRepository.getNextPageFavouriteProductList(obj.userId, obj.offset);
    });

}

///
public void setFavouritePostDataObj(String itemId, String userId) {

    if (!isLoading) {
        FavouriteViewModel.TmpDataHolder tmpDataHolder = new FavouriteViewModel.TmpDataHolder();
        tmpDataHolder.itemId = itemId;
        tmpDataHolder.userId = userId;

        sendFavouriteDataPostObj.setValue(tmpDataHolder);
        setLoadingState(true);
    }

}

//region Getter And Setter for item detail List
public void setItemFavouriteListObj(String loginUserId, String offset) {
    if (!isLoading) {
        FavouriteViewModel.TmpDataHolder tmpDataHolder = new FavouriteViewModel.TmpDataHolder();
        tmpDataHolder.userId = loginUserId;
        tmpDataHolder.offset = offset;
        itemFavouriteListObj.setValue(tmpDataHolder);

        // start loading
        setLoadingState(true);
    }
}

public LiveData<Resource<List<Item>>> getItemFavouriteData() {

    return itemFavouriteData;
}

public LiveData<Resource<List<ItemMoto>>> getItemFavouriteDataMoto() {

    return itemFavouriteDataMoto;
}

public LiveData<Resource<Boolean>> getFavouritePostData() {
    return sendFavouritePostData;
}

class TmpDataHolder {
    public String itemId = "";
    public String userId = "";
    public String cityId = "";
    public String offset = "";
}

}

当我检查最喜欢的产品时,我会看到 Item 的产品。我刷新,然后我看到 ItemMoto 的产品,但从来没有在一起。

【问题讨论】:

    标签: android android-room android-livedata android-architecture-components


    【解决方案1】:

    为什么不使用“3rd LiveData”之类的简单方法作为组合值?

    MutableLiveData<ItemMoto> mMotoLiveData = new MutableLiveData<>();
    MutableLiveData<ItemFavorite> mFavoriteLiveData = new MutableLiveData<>();
    MutableLiveData<Pair<ItemMoto,ItemFavorite>> mCombinedLiveData = new MutableLiveData<>();
    ItemMoto mLastItemMoto = null;
    ItemFavorite mLastItemFavorite = null;
    ...
    mMotoLiveData.observe(..., onChanged(@Nullable ItemMoto moto){
      mLastItemMoto = moto;
      mCombinedLiveData.postValue(new Pair<>(mLastItemMoto, mLastItemFavorite));
    });
    mFavoriteLiveData.observe(..., onChanged(@Nullable ItemFavorite favorite){
      mLastItemFavorite = favorite;
      mCombinedLiveData.postValue(new Pair<>(mLastItemMoto, mLastItemFavorite));
    });
    mCombinedLiveData.observe(..., onChanged(@NonNull Pair<ItemMoto,ItemFavorite> pair){
      //pair.one and/or pair.second could be NULL, so pay attention!!
    });
    

    注意 LiveData "onChanged()" 事件不会被所有 "postValue()" 调用触发,因为如果它们过于频繁,只有少数(或最新的)会触发它们的 onChanged() 事件,所以如果您希望使用 LiveDatas 获得 ItemMoto+ItemFavorite 的 所有组合 对您没有用处。

    【讨论】:

    • 我已经更新了我的问题。请看一下
    • 我尽量不使用第三方库,所以我的建议是基于我个人的想法。查看库源代码似乎(但我读得很快)它类似于我的解决方案,通过在两个初始 LiveDatas 上使用 Mediator 和每个 observe()。如果您需要了解问题所在,请放置一些断点,然后进入库以查看返回 NULL 的原因。当用户使用大多数程序员不经常使用的第三个库时,很难帮助他们.....
    猜你喜欢
    • 2021-12-08
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多