https://kotlinlang.org logo
#coroutines
Title
# coroutines
u

ursus

10/18/2020, 2:17 AM
Hi, im migrating from rx java. Is there a way to make this flow synchrounous on main thread in android?
Copy code
class MainActivity : AppCompatActivity() {

    private val scope = MainScope()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

		Log.d("Default", "a")
        scope.launch {
            Log.d("Default", "b")
            flowOf(1)
                .collect { Log.d("Default", "coll=$it t=${Thread.currentThread().name}") }
        }
        Log.d("Default", "c")
    }
}

prints:
2020-10-18 04:14:26.808 21786-21786/sk.foo.flowplayground D/Default: a
2020-10-18 04:14:26.808 21786-21786/sk.foo.flowplayground D/Default: c
2020-10-18 04:14:26.848 21786-21786/sk.foo.flowplayground D/Default: b
2020-10-18 04:14:26.851 21786-21786/sk.foo.flowplayground D/Default: coll=1 t=main

I want:
2020-10-18 04:14:26.808 21786-21786/sk.foo.flowplayground D/Default: a
2020-10-18 04:14:26.808 21786-21786/sk.foo.flowplayground D/Default: b
2020-10-18 04:14:26.848 21786-21786/sk.foo.flowplayground D/Default: coll=1 t=main
2020-10-18 04:14:26.851 21786-21786/sk.foo.flowplayground D/Default: c
i

Ian Lake

10/18/2020, 2:45 AM
What is
MainScope()
? I think if you use
lifecycleScope
you'll get the behavior you want since it uses
Dispatchers.Main.immediate
by default
u

ursus

10/18/2020, 2:46 AM
its from the standard library
Copy code
package kotlinx.coroutines

public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)
ill try the immediate thanks
@Ian Lake yep works exactly as you said. thanks!
i

Ian Lake

10/18/2020, 3:18 AM
lifecycleScope
also automatically handles cancellation when the activity is destroyed, so you always consider using that over creating your own scope. See the docs for more details: https://developer.android.com/topic/libraries/architecture/coroutines#lifecyclescope
u

ursus

10/18/2020, 3:20 AM
I'm aware, im however not using fragments/so my viewmodels are custom class and I need to manually handle the main thread scope
i

Ian Lake

10/18/2020, 3:26 AM
Ah, your example code was in an activity, that was what was throwing me off
u

ursus

10/18/2020, 3:28 AM
Yea just to show a minimal example, sorry. Also having that function in the core library feels kind of weird, what if I want the immediate as default, now I have to find some other good name or mess with imports and shoot my self in the foot
z

Zach Klippenstein (he/him) [MOD]

10/18/2020, 3:38 PM
In general it's better to inject your dispatchers instead of hard-coding them, and then you can just change the dispatcher that gets injected. This is a good practice for Rx too for that matter.
u

ursus

10/18/2020, 4:12 PM
sure .. its just a minimal repro; and commenting on necessity of such function in the library
z

Zach Klippenstein (he/him) [MOD]

10/18/2020, 5:16 PM
yea agree there – i think there are a few too many “conveniences” in the lib.
GlobalScope
is another one.
u

ursus

10/18/2020, 6:48 PM
also when its kinda harmful, doesnt expose the immediate as parameter etc, and now its public so its there forever
3 Views