Как вызывать методы в части приложения Dart с собственной платформы с помощью MethodChannel?

Я пишу собственный плагин, который в некоторых случаях должен вызывать функции в части Flutter приложения, написанной на Dart. Как это достигается, объясняется здесь: https://flutter.io/platform-channels/.

Кроме того, здесь приведен пример вызова метода из нативной / платформенной части по отношению к Dart / non-native: https://github.com/flutter/plugins/tree/master/packages/quick_actions

Теперь этот пример действительно хорош в случае, если платформе нужно только вызвать method, то есть этот вызов ничего не возвращает / void, но в случае, если ему нужно вызвать function, т.е. требуется возвращаемое значение из неродной части / Dart, Я не смог найти в Интернете пример или документацию. Я считаю, что это можно реализовать, потому что в нативной части Java есть метод:

public void invokeMethod(String method, Object arguments, MethodChannel.Result callback)

Итак, есть объект callback, который может иметь возвращаемое значение из неродной части - или, я ошибаюсь, и в настоящее время нет способа вернуть значение из неродной части приложения Dart?


person 2beens    schedule 05.05.2018    source источник
comment
Можете ли вы взглянуть на это - stackoverflow.com/ questions / 63581385 /?   -  person    schedule 26.08.2020


Ответы (1)


Подпись void setMethodCallHandler(Future<dynamic> handler(MethodCall call)), поэтому нам нужно предоставить функцию на конце Dart, которая возвращает Future<dynamic>, например _channel.setMethodCallHandler(myUtilsHandler);

Затем реализуйте обработчик. Этот обрабатывает два метода foo и bar, возвращающие соответственно String и double.

  Future<dynamic> myUtilsHandler(MethodCall methodCall) async {
    switch (methodCall.method) {
      case 'foo':
        return 'some string';
      case 'bar':
        return 123.0;
      default:
        throw MissingPluginException('notImplemented');
    }
  }

В конце Java возвращаемое значение передается методу success обратного вызова Result.

channel.invokeMethod("foo", arguments, new Result() {
  @Override
  public void success(Object o) {
    // this will be called with o = "some string"
  }

  @Override
  public void error(String s, String s1, Object o) {}

  @Override
  public void notImplemented() {}
});

В Swift возвращаемое значение - это Any?, переданное в закрытие result. (Не реализовано, сигнализируется параметром any, имеющим значение const NSObject FlutterMethodNotImplemented.)

channel.invokeMethod("foo", arguments: args, result: {(r:Any?) -> () in
  // this will be called with r = "some string" (or FlutterMethodNotImplemented)
})
person Richard Heap    schedule 05.05.2018
comment
Спасибо за это! У вас есть образцы кода для вызова из IOS, Swift? Большое спасибо! - person Tom; 29.07.2019
comment
@Tom - добавлен пример Swift - person Richard Heap; 29.07.2019
comment
@RichardHeap будет ли это, когда добавление неактивно? Например, когда диспетчер сигналов тревоги Android запускает широковещательный приемник? - person Robin Dijkhof; 23.08.2019
comment
Как использовать это в плагине Flutter? код Android вернет сообщение методу файла plugin.dart, но как файл main.dart использует этот метод? - person Darshan Pania; 03.11.2019
comment
Вашему плагину нужен initialize или аналогичный метод. Вы вызываете это из main или подобного, передавая некоторые функции или конкретную реализацию интерфейса. Плагин запоминает это / это. Затем, когда вы получаете вызов из родного языка, он выполняется следующим образом: основная (функция / интерфейс, упомянутые выше) ‹- плагин / Dart‹ - канал метода ‹- плагин / родной‹ - собственный вызов - person Richard Heap; 04.11.2019
comment
См. Также этот ответ, где вопрос заключался в том, можно ли не иметь функцию «инициализировать», на которую ответ, конечно же, отрицательный. stackoverflow.com/questions/58573536/ - person Richard Heap; 04.11.2019
comment
У меня такая ошибка: C:\...\ApplinkActivity.java:56: error: cannot find symbol CHANNEL.invokeMethod("foo", 12, new Result() { symbol: class Result location: class ApplinkActivity Что такое Result? - person Mohsen Emami; 04.12.2019
comment
Result - это интерфейс, который вы должны реализовать. Лучше всего задать свой вопрос, показывая свой код. - person Richard Heap; 04.12.2019
comment
как создать экземпляр channel на стороне java / kotlin ?? - person codeKiller; 20.01.2020
comment
@codeKiller Вы создаете его с new MethodChannel в своей onAttachedToEngine реализации. Хороший пример: github.com/flutter/plugins/tree/master/packages/connectivity/ - person Richard Heap; 20.01.2020
comment
@RichardHeap Когда я передаю список строк в качестве аргумента (например, channel.invokeMethod (foo, stringList, new Result ()), он выдает мне этот тип ошибки: «Список ‹dynamic›» не является подтипом типа «String». идея как это можно исправить ?? - person Ayush Malviya; 11.02.2020
comment
@Ayush Мне нужно больше контекста. Может задать новый вопрос. - person Richard Heap; 11.02.2020
comment
@RichardHeap, что это за конкретный код на стороне дротика (ваш случай по умолчанию с // todo), который вызовет FlutterMethodNotImplemented / notImplemented на стороне вызывающего? Ссылку найти не удалось. - person entonio; 06.07.2020
comment
@entonio Я думаю, throw MissingPluginException('notImplemented'); должен это сделать - person Richard Heap; 06.07.2020
comment
@RichardHeap действительно, спасибо. Я взял на себя смелость отредактировать ваш ответ, потому что считаю, что документации не хватает. - person entonio; 08.07.2020
comment
@RichardHeap Можете ли вы помочь в этом - https://stackoverflow.com/questions/63581385/flutter-plugin-call-back-on-dart - person ; 26.08.2020
comment
Не понял, как передавать аргументы с нативной стороны. Приведите, пожалуйста, образец. Мне действительно нужно передать список объектов - person David Papirov; 07.07.2021
comment
@DavidPapirov Для передачи списка используйте эквивалент платформы - например, для Java используйте ArrayList. Передайте его как параметр args - см. Заголовок stackoverflow.com/questions/57035150/ Обратите внимание, что вы не можете передать произвольный объект, если он не находится в списке типов, поддерживаемых кодеком сообщения (например, строка, карта и т. д.). Вы можете превратить произвольные объекты в карты поддерживаемых элементов или JSON или написать собственный кодек. - person Richard Heap; 07.07.2021
comment
@DavidPapirov См. Также: stackoverflow.com/questions/61507418/ - person Richard Heap; 07.07.2021