Kotlinx.coroutines: Using Job with CoroutineScope not starting the coroutine

Created on 27 May 2019  路  8Comments  路  Source: Kotlin/kotlinx.coroutines

private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.Main + job )

fun loadInitial(){
  scope.launch{
     val result=api.request().await()
  }
}

This coroutine is not getting executed when I add the job to the scope. But removing the job from scope executes the coroutine. Is it an intended behavior or issue from my side?

question waiting for clarification

Most helpful comment

But removing the job from scope executes the coroutine

I suppose that you are calling clear manually. Once cancelled, the job can no longer have any children

All 8 comments

It should work.
Could you please provide a self-contained sample that exposes the problem?

I was using it inside the Android paging libraries DataSource class. Using the job with dispatchers didn't execute the scope.launch{} block

Well, again, it should work and it works on my machine.

Can you provide a self-contained snippet of code that I can copy-paste and run on my machine that exposes your problem?

 class Test @Inject constructor(private val apiService:ApiService){
     private val dataSourceJob = SupervisorJob()

    private val scope = CoroutineScope(
        Dispatchers.Main + dataSourceJob
    )

  fun loadInitial() {

        scope.launch {

                val response =
                    apiService.getUsers("square", "okhttp", 1).await()
            }
    }

     fun clear() {
        dataSourceJob.cancel()
    }

This is my Network service class. I am using retrofit to make the network calls:

interface ApiService {
    @GET("repos/{owner}/{repo}/pulls?state=open")
    fun getUsers(
        @Path("owner") owner: String,
        @Path("repo") repo: String, @Query("page") page: Int
    ): Deferred<List<PullRequests>>
}

I am using coroutines version 1.2.1

But removing the job from scope executes the coroutine

I suppose that you are calling clear manually. Once cancelled, the job can no longer have any children

Yes, I am calling clear manually. But even before I call clear the launch block is not getting called. Even if i cancel my scope can't I invoke the function again to relaunch the coroutine

Cancellation is a terminal state. This particular interface seems error-prone to me since there's no way to determine the state of the job from outside. If you do expose a clear method like this you should also consider making it an error to call loadInitial when the job isCompleted.

fun loadInitial() {
    check(!dataSourceJob.isCompleted)
    // ...
}

However, it would be better if you exposed a regular suspend function for loadInitial and allowed the caller to control the lifecycle directly without introducing new interface for it.

suspend fun initialLoad() {
    // ...
}

Got it. The way I have architected my classes is wrong. Thanks for pointing out.
PS: @objcode Is there no way I can restart a job once it is canceled, like in RxJava

Was this page helpful?
0 / 5 - 0 ratings