Search code examples
androidkotlinkotlin-coroutinesandroid-livedatakotlin-flow

best way to convert flow to live data


I am implementing search from Unsplash api and data will be updated on the basis of search

GalleryViewModel.kt

@HiltViewModel
class GalleryViewModel @Inject constructor(
    private val fetchPhotoUseCase:FetchPhotoUseCase,
    @Assisted state: SavedStateHandle
) :ViewModel(){

    companion object{
        private const val CURRENT_QUERY = "current_query" // key
        private const val DEFAULT_QUERY = "cats"
    }

    private val currentQuery = state.getLiveData(CURRENT_QUERY, DEFAULT_QUERY)
    
    val photos = currentQuery.switchMap { queryString ->
        liveData {
            fetchPhotoUseCase.execute(queryString).collect {  
                emit(it)
            }
        }
    }

   fun searchPhotos(query: String) {
    currentQuery.value = query
   }
}

FetchPhotoUseCase.kt

class FetchPhotoUseCase @Inject constructor(
    private val repository: UnSplashRepository
) : UseCaseWithParams<String,Flow<PagingData<UnsplashPhoto>>>(){
    override suspend fun buildUseCase(params: String): Flow<PagingData<UnsplashPhoto>> {
        return repository.getSearchResult(params)
    }
}

FetchPhotoUseCase is in the domain layer. It returns flow so I change flow to live data in switchmap lambda.

Am I doing it right or is there a better way to achieve it..

Edit

I have updated my code to work on both dispatchers like below..

suspend fun getPhotos(queryString: String) = withContext(Dispatchers.IO){
        fetchPhotoUseCase.execute(queryString)
    }

    fun getImages(queryString: String) = liveData(Dispatchers.Main) {
        getPhotos(queryString).collect {
            emit(
                it.map { unsplash ->
                    unSplashMapper.mapFromEntity(unsplash)
                }
            )
        }
    }

Solution

  • There is a handy method asLiveData, which already implements of what you have written:

    val photos = currentQuery.switchMap { queryString ->
        fetchPhotoUseCase.execute(queryString).asLiveData(Dispatchers.Main)
    }
    

    Dependency to use asLiveData() extension function:

    def lifecycle_version = "2.4.0"
    
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"