Что такое PDD (Platform-Dependent Development) во Flutter?

Ответ

PDD (Platform-Dependent Development) во Flutter — это подход, при котором мы пишем платформо-специфичный код для доступа к нативным API или компонентам, которые не абстрагированы фреймворком. Это позволяет сохранять преимущества кроссплатформенности для UI-логики, но при необходимости использовать всю мощь iOS и Android.

Основные инструменты для PDD во Flutter:

  1. MethodChannel / EventChannel: Для вызова нативных методов и получения потоковых событий.
  2. PlatformView (UiKitView / AndroidView): Для встраивания нативных виджетов (например, карты Google/Apple, WebView) прямо в дерево виджетов Flutter.
  3. Платформо-специфичный код в папках android/ и ios/: Модификация MainActivity.kt, AppDelegate.swift и т.д.

Пример: Создание собственного плагина для вибрации через MethodChannel.

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

import 'package:flutter/services.dart';

class VibrationPlugin {
  static const platform = MethodChannel('com.example/vibration');

  static Future<void> vibrate(Duration duration) async {
    try {
      await platform.invokeMethod('vibrate', duration.inMilliseconds);
    } on PlatformException catch (e) {
      print("Не удалось вызвать вибрацию: ${e.message}");
    }
  }
}

Android-сторона (Kotlin в MainActivity.kt):

import android.os.Vibrator
import android.os.VibrationEffect
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val channel = "com.example/vibration"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
            call, result ->
            if (call.method == "vibrate") {
                val ms = call.arguments as Long
                val vibrator = getSystemService(Vibrator::class.java)
                vibrator.vibrate(VibrationEffect.createOneShot(ms, VibrationEffect.DEFAULT_AMPLITUDE))
                result.success(null)
            } else {
                result.notImplemented()
            }
        }
    }
}

Когда это нужно:

  • Интеграция со специфичными сервисами (Apple Pay, Google Play Billing).
  • Использование аппаратных датчиков, не охваченных стандартными плагинами.
  • Встраивание сложных нативных UI-компонентов. Сила Flutter в гибридном подходе: 90% кода — кроссплатформенный Dart, 10% — PDD для критически важной нативной функциональности.

Ответ 18+ 🔞

Э, слушай, вот тебе история про то, как заставить твой Flutter-проект делать такие фокусы, на которые он из коробки не способен. Это называется PDD (Platform-Dependent Development), и если по-простому — это когда ты пишешь код специально под каждую платформу, чтобы достучаться до её нативных фишек, которые фреймворк сам не покажет. Получается, интерфейс у тебя общий, красивый, а под капотом для особых случаев — вся мощь iOS и Android, ёпта.

Чем ты можешь колдовать:

  1. MethodChannel / EventChannel: Это как прямой провод к нативу. Через него можно методы вызывать и события слушать. Без него нихуя.
  2. PlatformView (UiKitView / AndroidView): Вот это вообще магия. Позволяет впихнуть нативный виджет (типа карты или WebView) прямо в твой Flutter-интерфейс. Выглядит так, будто так и было задумано.
  3. Ковыряние в папках android/ и ios/: Ну тут всё понятно, лезешь в MainActivity.kt или AppDelegate.swift и делаешь, что надо. Доверия ебать ноль, когда начинаешь там что-то менять, но без этого никак.

Давай на живом примере: сделаем плагин для вибрации через MethodChannel. Проще некуда.

Со стороны Flutter (Dart):

import 'package:flutter/services.dart';

class VibrationPlugin {
  static const platform = MethodChannel('com.example/vibration');

  static Future<void> vibrate(Duration duration) async {
    try {
      await platform.invokeMethod('vibrate', duration.inMilliseconds);
    } on PlatformException catch (e) {
      print("Не удалось вызвать вибрацию: ${e.message}");
    }
  }
}

А теперь со стороны Android (Kotlin в MainActivity.kt):

import android.os.Vibrator
import android.os.VibrationEffect
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val channel = "com.example/vibration"

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
            call, result ->
            if (call.method == "vibrate") {
                val ms = call.arguments as Long
                val vibrator = getSystemService(Vibrator::class.java)
                vibrator.vibrate(VibrationEffect.createOneShot(ms, VibrationEffect.DEFAULT_AMPLITUDE))
                result.success(null)
            } else {
                result.notImplemented()
            }
        }
    }
}

Когда вся эта возня нужна?

  • Когда надо интегрировать что-то уникальное, вроде Apple Pay или Google Play Billing.
  • Если хочешь использовать какой-нибудь экзотический датчик, для которого плагина ещё не написали.
  • Для встраивания сложных нативных UI-штук, которые на чистом Dart сделать — пиздопроебибна.

Вот и весь секрет. Сила Flutter как раз в этом гибридном подходе: 90% кода пишешь на Dart один раз, а оставшиеся 10% — это PDD для тех моментов, когда без нативной мощи просто овердохуища не обойтись.