java.lang.RuntimeException: @UiThread 标记的方法必须在主线程上执行。当前线程:DefaultDispatcher-worker-2
java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: DefaultDispatcher-worker-2
我对 flutter 和 kotlin 很陌生。我最近正在升级 flutter 版本(从 1.0.0 到 1.7.8+hotfix4)。我升级kotlin版本到1.3.10后,我的flutter app在尝试启动的时候崩溃了
错误显示如下:
[ +521 ms] E/AndroidRuntime( 2726): FATAL EXCEPTION: DefaultDispatcher-worker-2
[+1 ms] E/AndroidRuntime( 2726): Process: XXXXXXXXXXXX, PID: 2726
[ ] E/AndroidRuntime( 2726): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: DefaultDispatcher-worker-2
[ ] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:794)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.FlutterJNI.invokePlatformMessageResponseCallback(FlutterJNI.java:727)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:140)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.success(MethodChannel.java:225)
[ +1 ms] E/AndroidRuntime( 2726): at XXXXXXXXXXXX.MainActivity$onActivityResult.invokeSuspend(MainActivity.kt:91)
[ ] E/AndroidRuntime( 2726): at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
[ +14 ms] D/AutoManageHelper( 2726): onStart true {99992=com.google.android.gms.internal.zzbau$zza@72d039a}
[ +983 ms] I/CrashlyticsCore( 2726): Crashlytics report upload complete: 5D72013C01D2-0001-0AA6-12B9D92A3973
这是build.gradle
中的设置:
ext.kotlin_coroutines_version = "1.3.0"
ext.okhttp_version = "3.12.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlin_coroutines_version"
这是MainActivity
中的代码:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
LOGIN_CODE ->
if (resultCode == RESULT_OK) {
if (LoginManager.getInstance().loginService.isLoggedIn) {
GlobalScope.launch {
async {
var ls = LoginManager.getInstance().loginService
var response = ls.authRequest<AuthResponse<TokenResult>>(AUTH_PROVIDER_NAME)
return@async response.getToken()
}.await().let {
methodResult?.success(it)
}
}
}
} else {
methodResult?.success("")
}
LOGOUT_CODE ->
if (resultCode == RESULT_OK) {
methodResult?.success(true)
}
REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA -> {
if (resultCode != RESULT_OK) {
methodResult?.success("")
}
}
else -> {
methodResult?.success(false)
}
}
}
首先你应该避免使用全局作用域,它相当于在java中创建一个线程,你可以阅读更多here关于这个的内容。
其次,您应该知道只能在主线程上修改 UI。很可能 methodResult?.success(it)
做了一些 UI 更新,所以如果你想要快速修复:
GlobalScope.launch {
async {
var ls = LoginManager.getInstance().loginService
var response = ls.authRequest<AuthResponse<TokenResult>>(AUTH_PROVIDER_NAME)
return@async response.getToken()
}.await().let {
withContext(Dispatchers.Main) {
methodResult?.success(it)
}
}
}
当您调用 GlobalScope.launch
时,它意味着您启动协程,因为 Dispatchers.Default
意味着它将创建一个通常用于密集计算的工作线程,如果您使用它对于网络请求,更好的解决方案是使用调度程序 IO 启动它:
// instead of GlobalScope.launch
CoroutineScope(Dispatchers.IO).launch {
// your code goes here
}
我对 flutter 和 kotlin 很陌生。我最近正在升级 flutter 版本(从 1.0.0 到 1.7.8+hotfix4)。我升级kotlin版本到1.3.10后,我的flutter app在尝试启动的时候崩溃了
错误显示如下:
[ +521 ms] E/AndroidRuntime( 2726): FATAL EXCEPTION: DefaultDispatcher-worker-2
[+1 ms] E/AndroidRuntime( 2726): Process: XXXXXXXXXXXX, PID: 2726
[ ] E/AndroidRuntime( 2726): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: DefaultDispatcher-worker-2
[ ] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:794)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.FlutterJNI.invokePlatformMessageResponseCallback(FlutterJNI.java:727)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.embedding.engine.dart.DartMessenger$Reply.reply(DartMessenger.java:140)
[ +1 ms] E/AndroidRuntime( 2726): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.success(MethodChannel.java:225)
[ +1 ms] E/AndroidRuntime( 2726): at XXXXXXXXXXXX.MainActivity$onActivityResult.invokeSuspend(MainActivity.kt:91)
[ ] E/AndroidRuntime( 2726): at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
[ ] E/AndroidRuntime( 2726): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
[ +14 ms] D/AutoManageHelper( 2726): onStart true {99992=com.google.android.gms.internal.zzbau$zza@72d039a}
[ +983 ms] I/CrashlyticsCore( 2726): Crashlytics report upload complete: 5D72013C01D2-0001-0AA6-12B9D92A3973
这是build.gradle
中的设置:
ext.kotlin_coroutines_version = "1.3.0"
ext.okhttp_version = "3.12.0"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlin_coroutines_version"
这是MainActivity
中的代码:
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
LOGIN_CODE ->
if (resultCode == RESULT_OK) {
if (LoginManager.getInstance().loginService.isLoggedIn) {
GlobalScope.launch {
async {
var ls = LoginManager.getInstance().loginService
var response = ls.authRequest<AuthResponse<TokenResult>>(AUTH_PROVIDER_NAME)
return@async response.getToken()
}.await().let {
methodResult?.success(it)
}
}
}
} else {
methodResult?.success("")
}
LOGOUT_CODE ->
if (resultCode == RESULT_OK) {
methodResult?.success(true)
}
REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA -> {
if (resultCode != RESULT_OK) {
methodResult?.success("")
}
}
else -> {
methodResult?.success(false)
}
}
}
首先你应该避免使用全局作用域,它相当于在java中创建一个线程,你可以阅读更多here关于这个的内容。
其次,您应该知道只能在主线程上修改 UI。很可能 methodResult?.success(it)
做了一些 UI 更新,所以如果你想要快速修复:
GlobalScope.launch {
async {
var ls = LoginManager.getInstance().loginService
var response = ls.authRequest<AuthResponse<TokenResult>>(AUTH_PROVIDER_NAME)
return@async response.getToken()
}.await().let {
withContext(Dispatchers.Main) {
methodResult?.success(it)
}
}
}
当您调用 GlobalScope.launch
时,它意味着您启动协程,因为 Dispatchers.Default
意味着它将创建一个通常用于密集计算的工作线程,如果您使用它对于网络请求,更好的解决方案是使用调度程序 IO 启动它:
// instead of GlobalScope.launch
CoroutineScope(Dispatchers.IO).launch {
// your code goes here
}