Combine Two LiveData into one Android

639 views Asked by At

I need to combine these two Data. They both have their own Fragment,Dao, Model and Repository. And both return different data from different tables.

ItemFavourite table stores id of the tables aboves Item and ItemMoto.

   public LiveData<Resource<List<Item>>> getItemFavouriteData() {
            return itemFavouriteData;
   }
  //Moto
   public LiveData<Resource<List<ItemMoto>>> getItemFavouriteDataMoto() {
  return itemFavouriteDataMoto;
  }

This is how I tried it.

public class FavouriteViewModel extends PSViewModel {

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


@Inject
FavouriteViewModel(ItemRepository itemRepository, ItemMotoRepository itemMotoRepository) {

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


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

}

   public LiveData<Resource<List<Item>>> getItemFavouriteData() {
            return itemFavouriteData;
   }

   public LiveData<Resource<List<ItemMoto>>> getItemFavouriteDataMoto() {
   return itemFavouriteDataMoto;
   }

 private static LiveData<Resource<List<Item>>> mergeDataSources(LiveData... sources) {
    MediatorLiveData<Resource<List<Item>>> mergedSources = new MediatorLiveData();
    for (LiveData source : sources) {
        mergedSources.addSource(source, mergedSources::setValue);
    }
    return mergedSources;
}

public LiveData<Resource<List<Item>>> getFavourites() {
    return mergeDataSources(
            getItemFavouriteDataMoto(),
            getItemFavouriteData());
}

}

From Fragment I observe the data like this:

 LiveData<Resource<List<Item>>> news = favouriteViewModel.getFavourites();


    if (news != null) {

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

                switch (listResource.status) {
                    case LOADING:
                        // Loading State
                        // Data are from Local DB

                        if (listResource.data != null) {
                            //fadeIn Animation
                            fadeIn(binding.get().getRoot());

                            // Update the data
                            replaceData(listResource.data);

                        }

                        break;

                    case SUCCESS:
                        // Success State
                        // Data are from Server

                        if (listResource.data != null) {
                            // Update the data
                            replaceData(listResource.data);
                        }

                        favouriteViewModel.setLoadingState(false);

                        break;

                    case ERROR:
                        // Error State

                        favouriteViewModel.setLoadingState(false);
                        favouriteViewModel.forceEndLoading = true;

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

            }

        });
    }

The only data I am getting are from Item table only.

2

There are 2 answers

0
EpicPandaForce On

You can use MediatorLiveData and tuples, but you can technically also use this library I wrote for this specific purpose which does it for you, and solve it like this

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

private final LiveData<Pair<Resource<List<Item>>, Resource<List<ItemMoto>>>> favorites = combine(itemFavouriteData, itemFavouriteDataMoto, (favorites, favoriteMoto) -> {
    return Pair.create(favorites, favoriteMoto);
});

public LiveData<Pair<Resource<List<Item>>, Resource<List<ItemMoto>>>> getFavorites() {
    return favorites;
}
1
ninad thakare On

Using mediator live data we can observe the 2 livedata.

val groupChatFeed: LiveData<List<Feed<*>>> = MediatorLiveData<List<Feed<*>>>().apply {
    fun prepareDataAndSetStates(): List<Feed<*>> {
        val data: MutableList<Feed<*>> = mutableListOf()
        if (postList.value?.data?.isNullOrEmpty() == false) {
           data.addAll(postList.value?.data ?: emptyList())
        }
        if (connectionRecommendations.value?.data?.isNullOrEmpty() == false) {
           val recommendations = connectionRecommendations.value?.data?.toFeedItem()
           data.add(recommendations)
        }
        
        return data
    }

    addSource(postList) {
        value = prepareDataAndSetStates()
    }

    addSource(connectionRecommendations) {
        value = prepareDataAndSetStates()
    }
}

We are observing 2 different livedata postList and connectionRecommendations.