Как во Flutter взаимодействовать с нативным кодом платформы для обмена данными
Что проверяют
Знаете ли вы весь набор механизмов связи Dart с Android, а не только MethodChannel. Следом обычно спрашивают, в каком потоке выполняется нативный обработчик и как передать поток событий, например с датчика.
Как отвечать
Каналы асинхронны и ходят через BinaryMessenger движка. Три вида:
MethodChannel: вызов метода с ответом. Dart вызываетinvokeMethod, на Android вMainActivity : FlutterActivityили в плагине регистрируетсяsetMethodCallHandler, ответ уходит черезresult.success,result.error(в Dart этоPlatformException) илиresult.notImplemented(в DartMissingPluginException);EventChannel: поток событий из нативного кода в Dart-Stream. На Android реализуетсяStreamHandlerсonListenиonCancel, вonCancelнужно снимать слушателей;BasicMessageChannel: обмен сообщениями с выбранным кодеком без семантики вызова.
StandardMessageCodec передаёт null, bool, числа, строки, байтовые и числовые массивы, List и Map. Свои классы так не пройдут: их раскладывают в Map или берут Pigeon. Он генерирует типобезопасные интерфейсы для Dart и Kotlin из одного описания, и для нетривиального API это сейчас рекомендуемый путь.
Про потоки: обработчик по умолчанию вызывается в главном потоке Android. Тяжёлую работу уводите в корутину на Dispatchers.IO или регистрируйте канал с TaskQueue из makeBackgroundTaskQueue(). Вызовы из Kotlin в сторону Dart делайте из главного потока.
Для C и C++ есть dart:ffi без каналов и сериализации, для прямого вызова Java и Kotlin через JNI есть jnigen.
Где спотыкаются
Делают тяжёлую работу прямо в обработчике. Он крутится в главном потоке, интерфейс подвисает, на долгих операциях ловится ANR.
Вызывают result дважды или не вызывают вовсе. В первом случае IllegalStateException о том, что ответ уже отправлен, во втором Future в Dart не завершится никогда.
Гоняют через канал большие объёмы: кадры камеры или мегабайтный JSON на каждый вызов. Сериализация и копирование съедают выигрыш, лучше текстуры, файлы или FFI. И ещё: после добавления нативного кода hot reload даёт MissingPluginException, нужна полная пересборка.