Создание первого приложения Flutter

Создание хорошего плагина Flutter

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

На текущий момент в каталоге насчитываются сотни плагинов для Flutter. Качество плагина — наиважнейшая вещь, независимо от автора плагина — это компания Google или частный разработчик. В этой статье мы рассмотрим, что такое хороший плагин и как написать такой самостоятельно.

Если вы только начинаете разрабатывать на Flutter, обратите внимание на статью Создание первого приложения Flutter и продолжение.

Сперва — функциональность, затем остальное

При написании плагина вы скорее всего попытаетесь использовать существующую нативную библиотеку. Для этого нужно взять API этой библиотеки и создать для неё эквивалентный API на Dart. Однако если API-интерфейсы существенно отличаются под разными платформами, начинаются проблемы.

При написании плагинов сначала думайте о функциональности, а не об API. К примеру, если вы пишете плагин локального хранилища, вам, вероятно, нужны API-интерфейсы, которые поддерживают хранение значений различных типов с возможностью их повторного вызова. После того, как вы определили, какую функциональность вы хотите заложить, подумайте о построение красивого Dart API:

class StoragePlugin {
  
  /// Читаем строку
  Future<String> getString(String key) async {}
  
  /// Записываем строку
  Future<void> setString(String key, String value) async {}
}

После того, как у вас будет Dart API, переходите к общему API, тогда и увидите, какие ваши вызовы API должны быть адаптированы к вызовам API библиотеки конкретной платформы:

class StoragePlugin {
  
  Future<String> getString(String key) async {
    if (Platform.isIos) {
      return await callMethodChannel('fetchValue', {'id': base64encode(key)});
    } else if (Platform.isAndroid) {
      return await callMethodChannel('fetchValue', {'id': key});
    }
  }
  
  Future<void> setString(String key, String value) async {
    if (Platform.isIos) {
      await callMethodChannel('setValue', {'id': base64encode(key), 'value': value});
    } else if (Platform.isAndroid) {
      await callMethodChannel('setValue', {'id': key, 'value': value});
    }
  }
}

Если вы хотите реализовать какую-то функциональность, которая не поддерживается какой-то платформой, совершенно нормально что этот API будет нерабочим в ней.

Вы должны следить за тем, чтобы приложение не падало в этом случае и всё было тщательно задокументировано. Также вы должны запросить отсутствующую функциональность с этой платформы, чтобы ваш плагин стал завершённым.

Избегайте использования специфичных для платформы API-методов

Flutter не привязан к какой-либо платформе, поэтому и в приложениях на Flutter не должно быть платформенных методов. Например, если у вас такой код:

if (Platform.isIos) {
  myPlugin.doIOSThing();
} else if (Platform.isAndroid) {
  myPlugin.doAndroidThing();
}

то переместите в плагин всю заботу о платформах и пишите так:

myPlugin.doThing();

Избегайте поддержки только одной платформы

Возможно, вы хотите начать с малого и написать плагин только под Android. Но к несчастью, после публикации его в каталоге, пользователи неподдерживаемых платформ будут сильно разочарованы в нём.

Однако, есть и примеры обратного: Android Intent. Intent-ы существуют только в Android, поэтому существование такого плагина совершенно нормально.

Сделайте плагин удобным для чтения и тестирования

Как правило, ваш плагин должен быть написан в основном на Dart.

  • Нативный слой как правило сложен для тестирования, т.к написан с применением библиотек, не работающих в эмуляторах.
  • Flutter написан большей частью на Dart. Приложения Flutter написаны на чистом Dart. При трассировке кода легче всего будет, если большая часть логики описана на Dart.

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

При написании расширяемого нативного кода, разбивайте функциональность на разные классы, которые можно будет легко покрыть юнит-тестами.

В идеале, нативный слой будет просто ожидать вызовов метода, пересылая их библиотеке, возвращая затем результат в Dart. Если же требуется выполнить какую-либо дополнительную работу, стремитесь описать её на стороне Dart. В конце концов, вы напишете меньше кода, так как логика, вероятно, будет одинакова на всех платформах.

Избегайте писать статические (или глобальные) методы

Вместо такого подхода:

Future<User> authenticate() async {
  // код...
}

используйте:

class AuthenticatePlugin {
  Future<User> authenticate() async {
    // код...
  }
}

это сделает плагин более удобным для тестирования на эмуляторах.

Почитайте также Stateful-виджеты должны исчезнуть: Stateful Builder

Плагины это один из лучших способов расширить функциональность  Flutter. Поделитесь в комментариях своим опытом создания плагинов!

Написано по материалам статьи «Writing a good Flutter plugin»

Подписывайтесь на новости Flutter! https://t.me/flutterdaily

Создание хорошего плагина Flutter

Разработчик: java, kotlin, c#, javascript, dart, 1C, python, php.

Пишите: @ighar. Buy me a coffee, please :).

Leave a Comment

Чтобы не пропустить новые статьи, оставь свой Email

Поздравляем вы подписаны на новости ТехноДжем!

TВо время отправки данных произошла ошибка. Попробуйте ещё раз

Оставляя свою почту