Search code examples
androidkotlinkotlinx.coroutines

Kotlin Coroutines: RxJava-like subscribe to running job / Check if coroutine is running


I have the following setup (simplified):

  • network manager (get data from backend)
  • repository (handle data and forward to ui)

I'm looking for a way to do the following with Coroutines:

  • Before reaching the target screen, I already start prefetching data while navigating to another screen.
  • When reaching the target screen I would like to check if the task is still running und if yes, "subscribe" to or wait for the result instead of starting a new redundant network job.

Is there a way to achieve this with Coroutines?


Solution

  • The solution is the following:

    When the app starts it triggers prefetching some data via the repository. The repository holds a job reference to the running coroutine. When reaching the target screen another method in the repository is invoked. In this method the app now simply checks if the job is still active, if yes it calls job.join() to wait for the execution to finish before continuing.

    This is a simplification of the problem. Please just focus on the solution of the problem: - start coroutine, - check if coroutine is still running, - if yes, wait for coroutine to finish before doing other logic

    In the repository it looks as follows:

    class Repository(private val networkManager: NetworkManager) {
        private var allObjectsJob: Job? = null
    
        fun getAllObjects(forceReload: Boolean = false) {
            allObjectsJob = launch {
                try {
                    val objects = networkManager.getAllObjects().await().filterNotNull()
                    // e.g. put all objects in map
                } catch (e: HttpException) {
                    // error handling
                }
            }
        }
    
        fun getObject(id: String) {
            launch {
                if (allObjectsJob != null && allObjectsJob!!.isActive) {
                    allObjectsJob!!.join()
                }
    
                // e.g. get object from map
            }
        }
    }