java.lang.RuntimeException: методы, отмеченные @UiThread, должны выполняться в основном потоке. Текущий поток: DefaultDispatcher-worker-2
Я новичок в флаттере и котлине. Недавно делаю флаттер-версию (с 1.0.0 до 1.7.8+hotfix4). После того, как я обновил версию kotlin до 1.3.10, мое приложение flutter вылетало при попытке запустить его.
И ошибка выглядит так:
[ +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$1.success(MethodChannel.java:225)
[ +1 ms] E/AndroidRuntime( 2726): at XXXXXXXXXXXX.MainActivity$onActivityResult$1.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)
}
}
}
1 ответ
Прежде всего вам следует избегать использования глобальной области видимости, это эквивалентно созданию потока в java, вы можете прочитать об этом здесь.
Во-вторых, вы должны знать, что вы можете изменять пользовательский интерфейс только в основном потоке. Скорее всегоmethodResult?.success(it)
делает некоторые обновления пользовательского интерфейса, поэтому, если вы хотите быстрое исправление:
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
Ведьма означает, что он создаст рабочий поток, который обычно используется для интенсивных вычислений, если вы используете его для сетевых запросов, лучшим решением было бы запустить его с диспетчерским вводом-выводом:
// instead of GlobalScope.launch
CoroutineScope(Dispatchers.IO).launch {
// your code goes here
}