问题
I'm quite new about flutter and kotlin. I'm doing flutter version up(from 1.0.0 to 1.7.8+hotfix4) recently. After I upgrade kotlin version to 1.3.10, my flutter app came into crash when I try to start it.
And the error shows like this :
[ +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
This is the setting in 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"
Here is the code in 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:
First of all you should avoid using global scope, it is equivalent to creating a thread in java, you can read more here about this.
Second thing is that you should know that you can modify UI only on the Main thread. Most probably methodResult?.success(it)
does some UI updates, so if you want a fast fix :
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)
}
}
}
When you call GlobalScope.launch
it implies that you launch the coroutine as Dispatchers.Default
witch means it will create a worker thread that is usually used for intensive computation, if you use it for network requests a better solution would be to launch it with dispatchers IO:
// instead of GlobalScope.launch
CoroutineScope(Dispatchers.IO).launch {
// your code goes here
}
来源:https://stackoverflow.com/questions/57817304/java-lang-runtimeexception-methods-marked-with-uithread-must-be-executed-on-th