You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
}

关键说明

  1. 挂起函数:添加suspend修饰符后,函数只能在协程或其他挂起函数中调用,不会阻塞调用线程。
  2. suspendCoroutine:将回调式的API转换为挂起函数,通过continuation.resume()传递结果,确保回调能在Main线程正常执行。
  3. 避免阻塞主线程:所有UI相关操作仍在Main线程执行,协程的异步等待不会阻塞主线程,保证Flutter的回调流程能正常完成。

内容的提问来源于stack exchange,提问作者Nicerday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:26:06