首页 > 解决方案 > MethodChannel 是否会缓冲消息,直到另一端“连接”?

问题描述

MethodChannel在 Android 端有一个:

    class MainActivity: FlutterActivity() {
      private var channel : MethodChannel? = null

      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        GeneratedPluginRegistrant.registerWith(this)

        channel = MethodChannel(flutterView, "com.foo.Bar")

        channel!!.invokeMethod("onCreate", "created")
      }
    }

在 Dart 方面,我这样做:

    void main() {
      _main();
    }

    Future<void> _main() async {
      ... // do some async init stuff


      const platform = MethodChannel('com.foo.Bar');
      platform.setMethodCallHandler((call) {
        print('com.foo.Bar');
        print(call.method);
        print(call.arguments);
        return null;
      });

      runApp(MyApp());
    }

运行代码时,我在应用程序日志中看不到相应的消息。

MethodChannel在 Android 端缓冲消息直到 Dart 端“连接”还是发送消息MainActivity.onCreate

标签: flutterflutter-platform-channel

解决方案


即使问题有点老,我发现自己也处于类似的情况。

我使用了android.intent.action.VIEW意图过滤器来允许我的应用程序打开文件。更准确的说,是想把打开文件的内容交给dart代码处理。

由于打开文件会启动应用程序,因此会在 dart 部分构建小部件树并创建方法通道之前调用方法调用。

因此,Native Android Part 需要等到 Dart Part 准备好。这可以通过监听渲染器来实现。

由于代码应该是可读的,因此使用 FlutterRenderer 上的扩展来增加代码的可读性:

fun FlutterRenderer.doAfterFirstRender(op: () -> Unit){

    // Check if flutter part is already available
    if (isDisplayingFlutterUi) {
        op()
    } else {
        addIsDisplayingFlutterUiListener(object :FlutterUiDisplayListener{
            override fun onFlutterUiNoLongerDisplayed() {
            }

            override fun onFlutterUiDisplayed() {
                removeIsDisplayingFlutterUiListener(this)
                op()
            }
        })
    }
} 

在代码中,您现在可以使用扩展轻松调用该方法:

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        // Check if the intent was from file
        if (intent.action != null
                && intent.action.equals(Intent.ACTION_VIEW)
                && intent.data != null) {


            // get the file name & content
            val fileName = getFileName(intent.data)
            val fileExtension = fileName.orEmpty().split('.').last().toLowerCase()

            // check if the file extension is allowed
            if (fileExtension in ALLOWED_FILE_EXTENSIONS) {

                // get the file content
                val reader = BufferedReader(InputStreamReader(
                        context.contentResolver.openInputStream(intent.data)))
                val content = reader.readText()
                reader.close()

                val methodName = when (fileExtension) {
                    "ixml" -> "importDataFile"
                    "gxml" -> "importStructureFile"
                    else -> ""
                }

               flutterEngine.renderer.doAfterFirstRender {
                   MethodChannel(flutterEngine.dartExecutor.binaryMessenger, IMPORT_FILE_CHANNEL)
                           .invokeMethod(methodName, content)
               }
            }
        }
    } 

推荐阅读