Android端(Kotlin)如何接收MethodChannel.Result?主线程阻塞问题求解
解决Android通过MethodChannel调用Flutter方法时的线程阻塞问题
问题场景
Android端通过MethodChannel调用Flutter方法并获取返回数据,期望接收Flutter通过success方法返回的结果。当前实现尝试用runBlocking阻塞主线程等待结果,但导致Flutter的回调流程被中断,无法正常接收返回值。
原实现代码
fun callFlutterMethod(flutterMethod: String, params: Map<String, String>): String? { var res: String? = null val deferred = CompletableDeferred<String>() var job = CoroutineScope(Main).launch { channel!!.invokeMethod(flutterMethod, params, object : MethodChannel.Result { override fun success(result: Any?) { println("MethodChannel.Result, success: $result") deferred.complete(result.toString()) } override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) { println("callFlutterMethod error: $errorCode, $errorMessage,$errorDetails") } override fun notImplemented() { println("callFlutterMethod error: notImplemented") } }) } runBlocking { launch { res=deferred.await() } } println("Android received result: $res") return res }
日志信息
08:44:05.926 W dispatcher 0x730b26c380 ~ ignoring unknown event type 0x736f6674 08:44:08.930 W dispatcher 0x730b26c380 ~ ignoring unknown event type 0x736f6674 08:44:11.823 E START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10600000 hwFlg=0x10 cmp=com.wordx.robot_one/com.wordx.ro_plugin.MainActivity bnds=[649,1604][857,1885] (has extras)} result: 2
问题原因
runBlocking会直接阻塞当前的Main/UI线程,而MethodChannel的回调方法(success/error/notImplemented)默认也是在Main线程执行的。这就造成了死锁:主线程被runBlocking占用,Flutter返回结果的回调无法得到执行机会,自然无法获取到返回值。
解决方案
将函数改为挂起函数,使用suspendCoroutine来异步等待MethodChannel的回调结果,避免阻塞主线程。
修改后的代码
import kotlinx.coroutines.suspendCoroutine suspend fun callFlutterMethod(flutterMethod: String, params: Map<String, String>): String? { return suspendCoroutine { continuation -> channel!!.invokeMethod(flutterMethod, params, object : MethodChannel.Result { override fun success(result: Any?) { val resultStr = result?.toString() println("MethodChannel.Result, success: $resultStr") continuation.resume(resultStr) } override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) { println("callFlutterMethod error: $errorCode, $errorMessage,$errorDetails") continuation.resume(null) // 也可以根据需求抛出异常:continuation.resumeWithException(Exception(errorMessage)) } override fun notImplemented() { println("callFlutterMethod error: notImplemented") continuation.resume(null) } }) } }
调用示例
必须在协程作用域中调用该挂起函数,不能直接在主线程阻塞调用:
// 在Activity或Fragment中调用 CoroutineScope(Dispatchers.Main).launch { val result = callFlutterMethod("your_flutter_method", mapOf("param1" to "value1")) println("Android received result: $result") // 在这里处理返回结果,比如更新UI }
关键说明
- 挂起函数:添加
suspend修饰符后,函数只能在协程或其他挂起函数中调用,不会阻塞调用线程。 - suspendCoroutine:将回调式的API转换为挂起函数,通过
continuation.resume()传递结果,确保回调能在Main线程正常执行。 - 避免阻塞主线程:所有UI相关操作仍在Main线程执行,协程的异步等待不会阻塞主线程,保证Flutter的回调流程能正常完成。
内容的提问来源于stack exchange,提问作者Nicerday
相关产品推荐
相关产品推荐

