joe voidable
joe voidable

Reputation: 43

Is there a way to add return to a coroutine?

I just want to know if it is possible for me to return activePodcastViewData. I get return not allow here anytime I tried to call it on the activePodcastViewData.Without the GlobalScope I do get everything working fine.However I updated my repository by adding suspend method to it.Hence I was getting Suspend function should only be called from a coroutine or another suspend function.

fun getPodcast(podcastSummaryViewData: PodcastViewModel.PodcastSummaryViewData): PodcastViewData? { val repo = podcastRepo ?: return null val url = podcastSummaryViewData.url ?: return null

    GlobalScope.launch {
                val podcast = repo.getPodcast(url)
                withContext(Dispatchers.Main) {
                    podcast?.let {
                        it.feedTitle = podcastViewData.name ?: ""
                        it.imageUrl = podcastViewData.imageUrl ?: ""
                        activePodcastViewData = PodcastView(it)
                        activePodcastViewData
                    }
                }
            }
            return null
        }

class PodcastRepo { val rssFeedService =RssFeedService.instance

suspend fun getPodcast(url:String):Podcast?{
    rssFeedService.getFeed(url)
    return Podcast(url,"No name","No Desc","No image")
}

Upvotes: 0

Views: 99

Answers (1)

Arkadiusz Mądry
Arkadiusz Mądry

Reputation: 549

I'm not sure that I understand you correctly but if you want to get activePodcastViewData from coroutine scope you should use some observable data holder. I will show you a simple example with LiveData.

At first, add implementation:

implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"

Now, in your ViewModel we need to create mutableLiveData to hold and emit our future data.

val podcastsLiveData by lazy { MutableLiveData<Podcast>() }

Here your method: (I wouldn't recommend GlobalScope, let's replace it)

fun getPodcast(podcastSummaryViewData: PodcastViewModel.PodcastSummaryViewData): PodcastViewData? {
    val repo = podcastRepo ?: return null
    val url = podcastSummaryViewData.url ?: return null
    CoroutineScope(Dispatchers.IO).launch {
        val podcast = repo.getPodcast(url)
        withContext(Dispatchers.Main) {
            podcast?.let {
                it.feedTitle = podcastViewData.name ?: ""
                it.imageUrl = podcastViewData.imageUrl ?: ""
                activePodcastViewData = PodcastView(it)
            }
        }
    }
    podcastsLiveData.postValue(activePodcastViewData)
}

As you can see your return null is turned to postValue(). Now you finally can observe this from your Activity:

viewModel.podcastsLiveData.observe(this) {
            val podcast = it
            //Use your data
        }
viewModel.getPodcast()

Now every time you call viewModel.getPodcast() method, code in observe will be invoked.

I hope that I helped some :D

Upvotes: 1

Related Questions