flutter - 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
?
解决方案
即使问题有点老,我发现自己也处于类似的情况。
我使用了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)
}
}
}
}
推荐阅读
- javascript - 处理 ember 和 rails 中的验证错误
- azure - 交换 Azure webapp 部署槽时,并非所有流量都进入生产
- notepad++ - 删除记事本++中两个字符串之间的特定字符串
- django - Django 强制 Python3
- php - 将表单值发送到多个页面(使用相同的按钮)
- ruby - 揭开 Ruby“纤维”内部的神秘面纱
- mysql - 检索索引数据或每组中的最后一条记录
- node.js - 在子账户中创建子账户
- javascript - 将带有 CSS 的 HTML 文件添加到另一个 HTML 文件
- google-cloud-platform - 通过保留时间戳、静默,使用 Google Cloud API 将音频转为文本并再次使用音频