← Назад к вопросам

Как реализуешь вызов нативного кода из Flutter?

2.7 Senior🔥 171 комментариев
#Нативная интеграция

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как реализуешь вызов нативного кода из Flutter?

Вызов нативного кода из Flutter реализуется через платформенные каналы (Platform Channels). Это основной механизм взаимодействия между кодом на Dart и нативным кодом платформы.

Основные подходы

1. MethodChannel — для синхронных и асинхронных вызовов

Это наиболее распространённый способ. MethodChannel позволяет вызывать методы нативного кода и получать результаты.

Flutter сторона (Dart):

import "package:flutter/services.dart";

class NativeCaller {
  static const platform = MethodChannel("com.example.app/native");
  
  Future<String> getBatteryLevel() async {
    try {
      final result = await platform.invokeMethod("getBatteryLevel");
      return "Battery level: $result%";
    } on PlatformException catch (e) {
      return "Error: ${e.message}";
    }
  }
}

Android сторона (Kotlin):

import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
  private val CHANNEL = "com.example.app/native"
  
  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
      .setMethodCallHandler { call, result ->
        when (call.method) {
          "getBatteryLevel" -> {
            val batteryLevel = getBatteryLevel()
            result.success(batteryLevel)
          }
          else -> result.notImplemented()
        }
      }
  }
}

iOS сторона (Swift):

import Flutter

class AppDelegate: UIResponder, UIApplicationDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(
      name: "com.example.app/native",
      binaryMessenger: controller.binaryMessenger
    )
    
    channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
      switch call.method {
      case "getBatteryLevel":
        result(100)
      default:
        result(FlutterMethodNotImplemented)
      }
    }
    
    return true
  }
}

2. EventChannel — для потока событий

Используется, когда нативный код отправляет события в Flutter:

Flutter сторона:

class LocationListener {
  static const stream = EventChannel("com.example.app/location");
  
  Stream<Map<String, double>> getLocationUpdates() {
    return stream.receiveBroadcastStream()
      .cast<Map<dynamic, dynamic>>()
      .map((dynamic event) => Map<String, double>.from(event));
  }
}

3. BasicMessageChannel — для передачи сообщений

Для простого обмена сообщениями:

class Messenger {
  static const channel = BasicMessageChannel(
    "com.example.app/messages",
    StringCodec()
  );
  
  Future<String> sendMessage(String message) async {
    return await channel.send(message) as String;
  }
}

Практический пример: доступ к GPS

class GeoLocation {
  static const platform = MethodChannel("com.example.app/geolocation");
  
  Future<Map<String, double>> getCurrentLocation() async {
    try {
      final Map<dynamic, dynamic> result = 
        await platform.invokeMethod("getCurrentLocation");
      return {
        "latitude": result["latitude"] as double,
        "longitude": result["longitude"] as double
      };
    } catch (e) {
      throw Exception("Ошибка получения геолокации");
    }
  }
}

Обработка ошибок

try {
  await platform.invokeMethod("someMethod");
} on PlatformException catch (e) {
  print("Code: ${e.code}");
  print("Message: ${e.message}");
} on MissingPluginException {
  print("Метод не реализован на платформе");
}

Типы данных и сериализация

Поддерживаемые типы: null, bool, int, double, String, Uint8List, List, Map.

await platform.invokeMethod("updateUser", {
  "id": 123,
  "name": "John Doe",
  "tags": ["flutter", "mobile"]
});

Лучшие практики

  • Обработка исключений — всегда оборачивайте вызовы в try-catch
  • Константные имена каналов — используйте одно имя везде
  • Типизация — явно указывайте типы результатов
  • Асинхронность — не блокируйте основной поток
  • Проверка наличия — убедитесь, что метод реализован на обеих сторонах

Платформенные каналы — это мощный инструмент для интеграции Flutter с нативным функционалом платформы.