diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt index 9a298ce..e3e3bb9 100644 --- a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt @@ -1,6 +1,7 @@ package cn.tursom.utils.coroutine import cn.tursom.core.cast +import cn.tursom.core.toHexString import kotlinx.coroutines.Job import java.util.concurrent.ConcurrentHashMap import kotlin.coroutines.CoroutineContext @@ -43,6 +44,8 @@ open class CoroutineLocal { return true } + override fun toString(): String = "CoroutineLocal@${hashCode().toHexString(false)}" + companion object { private val attachMap = ConcurrentHashMap, Any?>>() override fun toString(): String = attachMap.toString() diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainCoroutineDispatcherFactory.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainCoroutineDispatcherFactory.kt new file mode 100644 index 0000000..3ad4214 --- /dev/null +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainCoroutineDispatcherFactory.kt @@ -0,0 +1,13 @@ +package cn.tursom.utils.coroutine + +import kotlinx.coroutines.InternalCoroutinesApi +import kotlinx.coroutines.MainCoroutineDispatcher +import kotlinx.coroutines.internal.MainDispatcherFactory + +@Suppress("unused") +@InternalCoroutinesApi +class MainCoroutineDispatcherFactory : MainDispatcherFactory { + override val loadPriority: Int = 1 + + override fun createDispatcher(allFactories: List): MainCoroutineDispatcher = MainDispatcher +} \ No newline at end of file diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainDispatcher.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainDispatcher.kt index d8119a9..8847e1a 100644 --- a/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainDispatcher.kt +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/MainDispatcher.kt @@ -1,27 +1,42 @@ package cn.tursom.utils.coroutine +import cn.tursom.core.cast +import kotlinx.coroutines.ExecutorCoroutineDispatcher import kotlinx.coroutines.MainCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher import java.io.Closeable import java.lang.reflect.Field import java.lang.reflect.Modifier import java.util.concurrent.Executors +import java.util.concurrent.atomic.AtomicBoolean import kotlin.concurrent.thread import kotlin.coroutines.CoroutineContext object MainDispatcher : MainCoroutineDispatcher(), Closeable { - private val dispatcher = Executors.newSingleThreadExecutor { - thread(start = false, block = it::run, name = "mainDispatcher", isDaemon = false) + private val loaded = AtomicBoolean(false) + private val dispatcher: ExecutorCoroutineDispatcher = Executors.newSingleThreadExecutor { + thread(start = false, block = it::run, name = "MainDispatcher", isDaemon = false) }.asCoroutineDispatcher() - - fun init() { - val mainDispatcherLoader = Class.forName("kotlinx.coroutines.internal.MainDispatcherLoader") - val dispatcher = mainDispatcherLoader.getDeclaredField("dispatcher") + private var oldDispatcher: MainCoroutineDispatcher? = null + private val mainDispatcherLoader: Class<*> = Class.forName("kotlinx.coroutines.internal.MainDispatcherLoader") + private val dispatcherField: Field = mainDispatcherLoader.getDeclaredField("dispatcher").also { dispatcher -> dispatcher.isAccessible = true val mf: Field = Field::class.java.getDeclaredField("modifiers") mf.isAccessible = true mf.setInt(dispatcher, dispatcher.modifiers and Modifier.FINAL.inv()) - dispatcher.set(null, this) + } + + fun init() { + if (loaded.compareAndSet(false, true)) { + oldDispatcher = dispatcherField.get(null).cast() + dispatcherField.set(null, this) + } + } + + fun resume() { + if (loaded.compareAndSet(true, false) && oldDispatcher != null) { + dispatcherField.set(null, oldDispatcher) + } } override val immediate: MainCoroutineDispatcher get() = this diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt index 3eeb81a..faee0a1 100644 --- a/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/utils.kt @@ -218,4 +218,12 @@ fun combinedContext(coroutineContext: CoroutineContext): Boolean { left.set(coroutineContext, leftObj + CoroutineLocalContext()) } return true +} + +//fun CoroutineScope.runOnUiThread(action: suspend CoroutineScope.() -> Unit): Job { +// return launch(Dispatchers.Main, block = action) +//} + +suspend fun runOnUiThread(action: suspend CoroutineScope.() -> T): T { + return withContext(Dispatchers.Main, action) } \ No newline at end of file diff --git a/utils/src/main/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory b/utils/src/main/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory new file mode 100644 index 0000000..e4f9d18 --- /dev/null +++ b/utils/src/main/resources/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory @@ -0,0 +1 @@ +cn.tursom.utils.coroutine.MainDispatcherFactory \ No newline at end of file diff --git a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt index a91cd80..13bdd73 100644 --- a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt +++ b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt @@ -23,23 +23,29 @@ interface CoroutineLocalTest { } class Test : CoroutineScope by MainScope() { - suspend fun test(): Job { - println(this) + suspend fun test() { + testCoroutineLocal.set(1) println(coroutineContext) - return coroutineScope { - println(this) + coroutineScope { println(coroutineContext) - println(Thread.currentThread().name) delay(1) - return@coroutineScope launch { - println(Thread.currentThread().name) - } } } } suspend fun main() { - MainDispatcher.init() - Test().test().join() + //MainDispatcher.init() + runOnUiThread { + Test().test() + println(testCoroutineLocal.get()) + println(coroutineContext) + GlobalScope.launch(Dispatchers.Main) { + println(coroutineContext) + } + //runOnUiThread { + // println(coroutineContext) + // println(testCoroutineLocal.get()) + //} + } MainDispatcher.close() } \ No newline at end of file