Вызов нативного кода из Flutter: MethodChannel vs Flutter Native Bridge

Вызов нативного кода из Flutter: MethodChannel vs Flutter Native Bridge

FlutterPulse

Эта статья переведена специально для канала FlutterPulse. В этом канале вы найдёте много интересных вещей, связанных с Flutter. Не забывайте подписываться! 🚀

Flutter делает создание красивых кроссплатформенных приложений простым, но реальные приложения часто требуют прямого доступа к нативным Android или iOS...

От ручных Platform Channels к нулевому boilerplate в нативных вызовах

Flutter делает создание красивых кроссплатформенных приложений простым, но реальные приложения часто требуют прямого доступа к нативным Android или iOS API — будь то функции оборудования, платформенные SDK или существующий нативный код.

Flutter предоставляет MethodChannel в качестве официального решения.
Но сегодня новые инструменты вроде Flutter Native Bridge делают эту интеграцию намного проще.

В этой статье вы узнаете:

  • Как Flutter вызывает нативный код используя MethodChannel
  • Почему MethodChannel может стать избыточным по boilerplate-коду
  • Как Flutter Native Bridge предлагает более чистую альтернативу
  • Когда выбирать каждый подход в production-приложениях

Зачем Flutter-приложениям нужен нативный код?

Даже с богатой экосистемой Flutter, некоторые сценарии все еще требуют нативного доступа:

  • Платформенные SDK
  • Информация об устройстве (ОС, модель, сенсоры)
  • Унаследованный Android/iOS код
  • Операции, критичные к производительности
  • API, еще недоступные в Flutter-плагинах

Для решения этой задачи Flutter предоставляет platform channels.

Часть 1: Вызов нативного кода с помощью MethodChannel (официальный способ)

Что такое MethodChannel?

MethodChannel — это встроенный механизм Flutter для двунаправленной коммуникации между Dart и нативными платформами.

Как это работает:

  1. Flutter вызывает метод по имени
  2. Нативный код слушает этот метод
  3. Нативный код выполняет платформенную логику
  4. Результат возвращается асинхронно в Flutter

Шаг 1: Определение MethodChannel в Flutter

☢️ Примечание: Мы намеренно избегаем называть какой-либо вспомогательный класс NativeBridge во избежание путаницы с другими пакетами.
import 'package:flutter/services.dart';

class PlatformService {
  static const MethodChannel _channel =
      MethodChannel('com.example.platform');
  static Future<String> getPlatformVersion() async {
    final result =
        await _channel.invokeMethod<String>('getPlatformVersion');
    return result ?? 'Unknown';
  }
}

Шаг 2: Android реализация (Kotlin)

class MainActivity : FlutterActivity() {

private val CHANNEL = "com.example.platform"
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            CHANNEL
        ).setMethodCallHandler { call, result ->
            when (call.method) {
                "getPlatformVersion" -> {
                    result.success(
                        "Android ${android.os.Build.VERSION.RELEASE}"
                    )
                }
                else -> result.notImplemented()
            }
        }
    }
}

Шаг 3: Реализация для iOS (Swift)

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(
      name: "com.example.platform",
      binaryMessenger: controller.binaryMessenger
    )
    channel.setMethodCallHandler { call, result in
      if call.method == "getPlatformVersion" {
        result("iOS \(UIDevice.current.systemVersion)")
      } else {
        result(FlutterMethodNotImplemented)
      }
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

Недостатки MethodChannel

Несмотря на мощь, MethodChannel имеет ряд недостатков:

  • ❌ Ручное сопоставление имен методов
  • ❌ Громоздкий код на обеих платформах
  • ❌ Отсутствие безопасности на этапе компиляции
  • ❌ Сложность масштабирования по мере роста API
  • ❌ Отсутствие автодополнения IDE для нативных методов

Вот где Flutter Native Bridge сияет.

Часть 2: Flutter Native Bridge — Современная альтернатива MethodChannel

Flutter Native Bridge — это zero-boilerplate bridge, который позволяет вам вызывать нативные методы Kotlin/Swift напрямую из Dart — без необходимости вручную писать код MethodChannel.

Чем Flutter Native Bridge отличается?

  • ✅ Нет громоздкого кода MethodChannel
  • ✅ Автоматическое обнаружение нативных методов
  • ✅ Типобезопасные сгенерированные API Dart
  • ✅ Автодополнение в IDE
  • ✅ Работает на Android (Kotlin) и iOS (Swift)
  • ✅ Не требует KSP или аннотационных процессоров

Установка

dependencies:
  flutter_native_bridge: ^1.0.0

Настройка Android (Kotlin)

Вариант 1: Предоставить весь класс

@NativeBridge
class DeviceService {
    fun getModel(): String = Build.MODEL
    fun getVersion(): Int = Build.VERSION.SDK_INT

@NativeIgnore
    fun internalMethod() {}
}

Вариант 2: Предоставить отдельные методы

class MainActivity : FlutterActivity() {

@NativeFunction
    fun greet(name: String): String = "Hello, $name!"
}

Регистрация (одна строка)

FlutterNativeBridge.register(this)

Настройка iOS (Swift)

MethodChannel — это основа для нативной коммуникации в Flutter, но он никогда не проектировался для удобства разработки в крупных проектах.

Flutter Native Bridge основывается на той же концепции — без боли.

Если вы начинаете с нуля или рефакторите нативную интеграцию, Flutter Native Bridge может сэкономить часы на шаблонном коде и значительно уменьшить количество багов.


Report Page