@@ -8,8 +8,8 @@ package kotlinx.coroutines
8
8
9
9
import kotlinx.coroutines.internal.*
10
10
import kotlinx.coroutines.scheduling.*
11
- import kotlin.coroutines.*
12
11
import java.util.*
12
+ import kotlin.coroutines.*
13
13
14
14
/* *
15
15
* Name of the property that defines the maximal number of threads that are used by [Dispatchers.IO] coroutines dispatcher.
@@ -20,7 +20,6 @@ public const val IO_PARALLELISM_PROPERTY_NAME = "kotlinx.coroutines.io.paralleli
20
20
* Groups various implementations of [CoroutineDispatcher].
21
21
*/
22
22
public actual object Dispatchers {
23
-
24
23
/* *
25
24
* The default [CoroutineDispatcher] that is used by all standard builders like
26
25
* [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc
@@ -95,7 +94,21 @@ private object MainDispatcherLoader {
95
94
val dispatcher: MainCoroutineDispatcher =
96
95
MainDispatcherFactory ::class .java.let { clz ->
97
96
ServiceLoader .load(clz, clz.classLoader).toList()
98
- }.maxBy { it.loadPriority }?.tryCreateDispatcher() ? : MissingMainCoroutineDispatcher (null )
97
+ }.maxBy { it.loadPriority }?.tryCreateDispatcher()
98
+ ? : (tryLoadAndroidDispatcher() ? : MissingMainCoroutineDispatcher (null ))
99
+
100
+ private fun tryLoadAndroidDispatcher (): MainCoroutineDispatcher ? {
101
+ /*
102
+ * Latest Android toolchain (androidx) *sometimes* mangles the name of the service loaded by ServiceLoader even if
103
+ * it is present in the manifest. To workaround it (we don't want our users to suffer) we optimistically
104
+ * try to load android factory manually (implementation is not mangled because it is marked with @Keep)
105
+ */
106
+ val dispatcher = kotlin.runCatching {
107
+ val clazz = Class .forName(" kotlinx.coroutines.android.AndroidDispatcherFactory" )
108
+ clazz.getMethod(" getDispatcher" )?.invoke(null ) as MainCoroutineDispatcher
109
+ }
110
+ return dispatcher.getOrNull()
111
+ }
99
112
100
113
/* *
101
114
* If anything goes wrong while trying to create main dispatcher (class not found,
0 commit comments