Ответ
Да, у меня был опыт интеграции Kotlin Multiplatform (KMP) модуля в Flutter-приложение. Мы использовали KMP для написания общей бизнес-логики (например, валидации, моделей данных, некоторых репозиториев) на Kotlin, которую затем могли использовать и в нативной Android-части, и во Flutter.
Архитектура: В гибридном проекте UI был реализован на Flutter (единый для Android и iOS), а сложная доменная логика, общая с нативным Android-модулем, вынесена в KMP-модуль.
Интеграция KMP с Flutter:
- KMP-модуль компилируется в Android-библиотеку (
.aar) и iOS-фреймворк (.framework). - Для Android: KMP-модуль добавляется как зависимость в
android/build.gradleпроекта Flutter. - Для iOS: Сгенерированный фреймворк подключается к iOS-части Flutter-проекта через CocoaPods или вручную.
- Во Flutter-коде общая логика вызывается через platform channels.
Пример вызова KMP-кода из Flutter (через MethodChannel):
// Flutter-сторона (Dart)
import 'package:flutter/services.dart';
class KmpService {
static const platform = MethodChannel('com.example.kmp/channel');
Future<String> performBusinessLogic(String input) async {
try {
final result = await platform.invokeMethod('processData', input);
return result;
} on PlatformException catch (e) {
return "Error: '${e.message}'.";
}
}
}
// KMP / Android-сторона (Kotlin)
// В MainActivity.kt Flutter-проекта
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.kmp/channel")
.setMethodCallHandler { call, result ->
if (call.method == "processData") {
val input = call.arguments as String
// Вызов функции из общего KMP-кода!
val output = SharedBusinessLogic.process(input)
result.success(output)
} else {
result.notImplemented()
}
}
}
}
Плюсы подхода:
- Переиспользование кода: Сложная и критичная логика пишется один раз на Kotlin и работает на всех платформах.
- Безопасность и производительность: Kotlin — статически типизированный и производительный язык.
Сложности:
- Усложнение сборки: Необходимо настраивать сборку KMP-модуля и его интеграцию в Flutter.
- Оверхеад коммуникации: Вызовы через platform channel асинхронны и имеют некоторую задержку, что не подходит для высокочастотных операций.
Этот опыт показал, что KMP — мощный инструмент для sharing-кода, но его интеграция с Flutter требует тщательной архитектурной проработки.
Ответ 18+ 🔞
А, ну так вот, история про то, как мы впихнули Котлин Мультиплатформу во Флаттер. Ебать мои старые костыли, это был тот ещё опыт, чувак. В общем, была у нас идея — всякую мозговую, доменную логику (типа валидаций, моделек, репозиториев) писать один раз, а таскать её и в нативный андроид, и во флаттер. Ну, чтобы не дублировать, понимаешь? Овердохуища работы было бы.
Как это всё было устроено: Вся красота интерфейса — на Флаттере, один для всех. А вот под капотом, в самом сердце, где всё думает и решает — там сидел наш общий КМП-модуль, как какой-нибудь хитрая жопа.
Как мы это прикручивали:
- КМП-шный модуль мы настраивали так, чтобы он выплевывал на выходе библиотечку для андроида (
.aar) и фреймворк для айос (.framework). - Для Андроида: Просто пихали эту библиотеку как зависимость в
android/build.gradleфлаттеровского проекта. Вроде ничего сложного. - Для iOS: Тут уже веселее. Сгенерированный фреймворк надо было прицепить к айосовской части проекта. Через CocoaPods или вручную — кому как нравится, но волнение ебать, пока не заработает.
- А чтобы позвать эту логику из Флаттера — использовали старые добрые platform channels. Ну, мост такой, понимаешь.
Вот, смотри, как выглядел вызов (примерно):
// Со стороны Флаттера (Dart)
import 'package:flutter/services.dart';
class KmpService {
static const platform = MethodChannel('com.example.kmp/channel');
Future<String> performBusinessLogic(String input) async {
try {
final result = await platform.invokeMethod('processData', input);
return result;
} on PlatformException catch (e) {
return "Error: '${e.message}'.";
}
}
}
// Со стороны КМП / Андроида (Kotlin)
// Писали это в MainActivity.kt флаттеровского проекта
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.kmp/channel")
.setMethodCallHandler { call, result ->
if (call.method == "processData") {
val input = call.arguments as String
// А вот и магия! Зовём функцию из общего КМП-кода!
val output = SharedBusinessLogic.process(input)
result.success(output)
} else {
result.notImplemented()
}
}
}
}
Что в итоге было круто:
- Код не повторялся: Написали сложную логику один раз на Котлине — и она работает везде. Красота.
- Надёжность и скорость: Котлин — язык строгий, статический, без этих ваших динамических плясок. Работает чётко.
А что было пиздец как сложно:
- Сборка превратилась в ёперный театр: Настроить сборку КМП-модуля и его интеграцию — это отдельный квест на терпение. Терпения ноль ебать к концу настройки.
- Задержки в общении: Вызовы через platform channel — они асинхронные, с небольшой, но задержкой. Для высокочастотных штук, где каждый миллисекунд на счету, это не очень.
В общем и целом, опыт показал, что КМП — инструмент мощный, реально позволяет переиспользовать код по-взрослому. Но прилепить его к Флаттеру — это вам не хуй с горы скатить, тут надо головой думать и архитектуру продумывать заранее, а то потом сам от себя охуеешь.