Search code examples
androidkotlinkotlin-coroutinessealed-class

Coroutines with sealed class


My project has a lot of operations that must be performed one after another. I was using listeners, but I found this tutorial Kotlin coroutines on Android and I wanted to change my sever call with better readable code. But I think I am missing something. The below code always return an error from getTime1() function:

suspend fun getTimeFromServer1() :ResultServer<Long> {
        val userId = SharedPrefsHelper.getClientId()
        return withContext(Dispatchers.IO) {
            val call: Call<ResponseFromServer>? = userId?.let { apiInterface.getTime(it) }
            (call?.execute()?.body())?.run {
                val time:Long? = this.data?.time
                time?.let {
                    Timber.tag("xxx").e("time received it ${it}")// I am getting the right result here
                    ResultServer.Success(it)
                }
                Timber.tag("xxx").e("time received ${time}")
            }
            ResultServer.Error(Exception("Cannot get time"))
        }
    }


fun getTime1() {
        GlobalScope.launch {
            when (val expr: ResultServer<Long> = NetworkLayer.getTimeFromServer1()) {
                is ResultServer.Success<Long> -> Timber.tag("xxx").e("time is ${expr.data}")
                is ResultServer.Error -> Timber.tag("xxx").e("time Error") //I am always get here
            }}
    }
    }

But if I am using listeners (getTime()) everything works perfectly:

 suspend fun getTimeFromServer(savingFinishedListener: SavingFinishedListener<Long>) {
        val userId = SharedPrefsHelper.getClientId()
        withContext(Dispatchers.IO) {
            val call: Call<ResponseFromServer>? = userId?.let { apiInterface.getTime(it) }
            (call?.execute()?.body())?.run {
                val time:Long? = this.data?.time
                time?.let {
                    Timber.tag("xxx").e("time received it ${it}")
                    savingFinishedListener.onSuccess(it)
                }

            }
            savingFinishedListener.onSuccess(null)
        }
    }

   fun getTime() {
        GlobalScope.launch {
            NetworkLayer.getTimeFromServer(object:SavingFinishedListener<Long>{
                override fun onSuccess(t: Long?) {
                    t?.let {
                        Timber.tag("xxx").e("time here $it") //I am getting the right result
                    }
                }
            })
           }
        }

Thanks in advance for any help.


Solution

  • The last line of a lambda is implicitly the return value of that lambda. Since you don't have any explicit return statements in your withContext lambda, its last line:

    ResultServer.Error(Exception("Cannot get time"))
    

    means that it always returns this Error. You can put return@withContext right before your ResultServer.Success(it) to make that line of code also return from the lambda.

    Side note: don't use GlobalScope.