Общий интерфейс для двух плагинов Flutter

#flutter #dart #flutter-dependencies

Вопрос:

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

Я успешно реализовал оба плагина в качестве плагинов Flutter. Я хочу использовать их в приложении Flutter и использовать плагин, основанный на устройстве.

Я создал общий абстрактный класс для предоставления одного и того же API, но класс плагина flutter содержит все статические методы, которые не позволяют реализовать общий интерфейс.

Как мы можем предоставить общую реализацию dart из плагина и использовать ее взаимозаменяемо?

Для примера предположим, что у нас есть этот абстрактный класс в качестве общего интерфейса,

 abstract class Pluggable{
   void plug();
}

 

Класс плагина, который генерируется Flutter create, является,

 import 'dart:async';

import 'package:flutter/services.dart';

class MyPlugin {
  static const MethodChannel _channel = MethodChannel('my_plugin');

  static Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }

  static Future<void> plug() async {
    await _channel
        .invokeMethod('plug');
  }

}

 

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

Ответ №1:

Проблема в том, что ваш класс плагина flutter имеет абстрактные методы. Существует множество способов сделать это, от использования надлежащей структуры внедрения зависимостей для ввода нужного типа до использования поставщика или другой наследуемой оболочки Widget для хранения экземпляра нужного класса плагина и предоставления его обычным способом.

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

Я бы рекомендовал добавить статический инициализатор в ваш синглтон. См. Пример ниже.

 
// this declares the abstract class.
abstract class MyAbstractClass {
  static void initializeWith(MyAbstractClass instance) {
    _instance = instance;
  }

  // this could introduce a potential bug if you don't initialize
  // or try to do it multiple times, so make sure you do that
  // properly exactly once.
  static late final MyAbstractClass _instance;
  static MyAbstractClass get instance => _instance;

  // methods to show how this works
  void method1();
  void method2();
  
  // an example of how to call directly from the class
  static void doMethod1() => _instance.method1();
}

// one simple implementation
class MyClass1 implements MyAbstractClass {
  @override
  void method1() => print(1);
  @override
  void method2() => print(2);
}

// another simple implementation
class MyClass2 implements MyAbstractClass {
  @override
  void method1() => print("a");
  @override
  void method2() => print("b");
}

// and in practice, you simply have to initialize and then
// use however you'd like.
void main() {
//   MyAbstractClass.initializeWith(MyClass1());
//   MyAbstractClass.doMethod1();
//   MyAbstractClass.instance.method2();
  
  MyAbstractClass.initializeWith(MyClass2());
  MyAbstractClass.doMethod1();
  MyAbstractClass.instance.method2(); 
}
 

Вам придется преобразовать все ваши статические методы в члены, но это должно быть так же просто, как удалить любые статические ссылки и удалить статические ключевые слова.

Комментарии:

1. добавьте пример к вопросу