Что такое BasicMessageChannel в Flutter?

«Что такое BasicMessageChannel в Flutter?» — вопрос из категории Платформенное взаимодействие, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

BasicMessageChannel — это один из трёх основных каналов платформенных каналов (Platform Channels) в Flutter, предназначенный для асинхронной передачи простых сообщений (строк, чисел, списков, мап) между кодом на Dart и нативным кодом платформы (Kotlin/Java для Android, Swift/Obj-C для iOS).

Зачем он нужен? Для вызова нативных API, которые не имеют готовых плагинов, например, для работы со специфичным hardware, системными сервисами или нативными библиотеками.

Пример двухсторонней коммуникации (Dart <-> Kotlin):

1. Сторона Dart (Flutter):

import 'package:flutter/services.dart';

// Создаем канал. Имя 'com.example/app_channel' должно быть уникальным.
const _channel = BasicMessageChannel<String>(
  'com.example/app_channel',
  StringCodec(), // Используем стандартный кодек для строк
);

// Отправляем сообщение на платформу и ждем ответ
Future<void> sendMessageToNative() async {
  String response;
  try {
    final String reply = await _channel.send('Hello from Flutter!');
    response = 'Received reply: $reply';
  } on PlatformException catch (e) {
    response = 'Failed: ${e.message}';
  }
  print(response);
}

// Устанавливаем обработчик входящих сообщений с платформы
@override
void initState() {
  super.initState();
  _channel.setMessageHandler((String? message) async {
    print('Flutter received: $message');
    // Можно отправить ответ обратно
    return 'Ack from Flutter';
  });
}

2. Сторона Kotlin (Android):

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.StringCodec

class MainActivity: FlutterActivity() {
    private var channel: BasicMessageChannel<String>? = null

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // Создаем канал с таким же именем
        channel = BasicMessageChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example/app_channel",
            StringCodec.INSTANCE
        )
        // Устанавливаем обработчик
        channel?.setMessageHandler { message, reply ->
            Log.d("Native", "Received from Flutter: $message")
            // Отправляем ответ во Flutter
            reply.reply("Hello from Android!")
        }
    }
}

Ключевое отличие от других каналов:

  • MethodChannel: Используется для вызова конкретных методов (как API).
  • EventChannel: Для передачи потока событий (stream) от платформы к Dart.
  • BasicMessageChannel: Для свободного обмена сообщениями, когда структура вызовов не фиксирована строго в "методы".