Introdução e jornada avançada do Flutter (19) O Flutter interage com a plataforma nativa

introdução:

Depois de estudar os capítulos anteriores, acredito que os leitores tenham uma compreensão geral do Flutter e também possam usar alguns componentes básicos fornecidos pela plataforma Flutter para escrever alguma lógica de página simples. Alguns leitores podem até usar Flutter puro para desenvolver seu próprio aplicativo, mas muitos leitores podem achar que, em alguns cenários ou em algumas plataformas nativas, itens não podem ser obtidos do Flutter, como versão do sistema, nível da bateria, aplicativo de permissão dinâmica e outras APIs no nível do sistema. O Flutter não as forneceu diretamente para mim. Forneça APIs relevantes para operação. Neste momento, podemos precisar usar recursos nativos ou interagir com a plataforma nativa para obter esses dados.

Objetivos do curso

  • Compreender e dominar o método de comunicação entre flutter e nativo
  • Domine o mecanismo de implementação de retornos de chamada mútuos entre flutter e nativo por meio do MethodChannel
  • Domine a plataforma nativa para transmitir dados ativamente para o Flutter por meio do EventChannel
1. Flutter e comunicação nativa

Flutter se comunica com o lado nativo principalmente através de MethodChannel e EventChannel. MethodChannel e EventChannel são como tubos ou pontes, conectando o lado flutter com o lado nativo.
Vamos dar uma olhada na explicação oficial:

Um canal nomeado para comunicação com plug-ins de plataforma usando chamadas de método assíncronas
.

  • 1.) Assinatura do método MethodChannel
    public MethodChannel(BinaryMessenger messenger, String name) {
    
    
        this(messenger, name, StandardMethodCodec.INSTANCE);
    }
  • 2.) Assinatura do método EventChannel
    public EventChannel(BinaryMessenger messenger, String name) {
    
    
        this(messenger, name, StandardMethodCodec.INSTANCE);
    }

Para garantir a fluidez da interface do usuário durante o processo de interação, quer as mensagens sejam enviadas do Flutter para o lado nativo ou o nativo envie mensagens para o Flutter 异步的形式进行传递.

1. Durante todo o processo de interação, tanto o lado Flutter quanto o lado Nativo podem enviar ambas as extremidades para a outra plataforma através do MethodChannel para 提前定义好的方法名chamar a lógica de processamento de mensagens correspondente da outra plataforma e trazer de volta o valor de retorno ao receptor.
2. O cenário de uso do EventChannel é mais focado na plataforma nativa enviando ativamente mensagens unidirecionais para a plataforma Flutter. O Flutter não pode retornar nenhum dado para o lado nativo. O autor prefere descrever o EventChannel como unidirecional.

Até agora, temos uma compreensão simples da comunicação e interação entre o Flutter e o lado nativo. Vamos primeiro dar uma olhada nas renderizações de código a serem concluídas neste curso e, em seguida, ver os casos mencionados nas renderizações. Análise e explicação um por um um:

Interação da plataforma

2. Análise de caso de código de renderização
  • O lado Flutter chama a plataforma Native por meio do MethodChannel para abrir o Toast.
  • Flutter usa MechtondChannl para passar parâmetros para o lado Natvie para chamar funções relacionadas no lado Nativo.Depois que Native recebe os parâmetros, ele retorna os resultados processados ​​para o lado Flutter.
  • Flutter usa MethodChannel para abrir uma nova página nativa
  • O lado nativo usa MethodChannel para passar parâmetros para o lado Flutter e recebe os dados processados ​​repassados ​​do lado Flutter.
  • O lado nativo usa EventChannel para enviar dados (mensagens) ativamente para o lado Flutter.

A lógica de registro do método para interação entre ambas as extremidades também é relativamente simples. Os leitores saberão disso rapidamente, então não entrarei em muitas descrições. Aqui estão dois exemplos representativos de interação entre ambas as extremidades:

1. Flutter chama a função nativa, calcula a soma de dois números e obtém o resultado processado para o lado Flutter.
2. O lado Nativo usa EventChannel para enviar dados (mensagens) ativamente para o lado Flutter.

2.1 Flutter chama a função nativa, calcula a soma de dois números e obtém o resultado processado até o final do Flutter

Análise de cenário : pode ser comparada à lógica de negócios que não pode ser processada pelo lado Flutter. Nesse momento, os parâmetros necessários são passados ​​​​para o nativo, e o processamento nativo recebe os parâmetros. Após a conclusão do processamento, os resultados são enviado de volta ao lado do Flutter para completar toda a lógica de negócios.

Registrando o canal
Para garantir que Flutter e Native possam estabelecer comunicação normal, devemos primeiro garantir que 通道名o channelName do MethocChannel registrado em ambas as extremidades seja consistente. Registre o channelName em ambas as extremidades da seguinte forma:

Lado nativo:

private static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
 methodChannel = new MethodChannel(getFlutterView(), METHOD_CHANNEL);

Lado flutuante:

 static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
   static final MethodChannel _MethodChannel =MethodChannel(METHOD_CHANNEL); //平台交互通道

Lado Android:

public class MainActivity extends FlutterActivity {
    
    
    private static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
    private static final String METHOD_NUMBER_ADD = "numberAdd"; //简单加法计算,并返回两个数的和
    private MethodChannel methodChannel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        GeneratedPluginRegistrant.registerWith(this);


        methodChannel = new MethodChannel(getFlutterView(), METHOD_CHANNEL);
        //接受fltuter端传递过来的方法,并做出响应逻辑处理
        methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    
    
            @Override
            public void onMethodCall(MethodCall call, MethodChannel.Result result) {
    
    
                System.out.println(call.method);
               if (call.method.equals(METHOD_NUMBER_ADD)) {
    
    
                    int number1 = call.argument("number1");
                    int number2 = call.argument("number2");
                    result.success(number1 + number2); //返回两个数相加后的值
                } 
            }
        });

    }
    
}

Lado flutuante:

class AndroidPlatformPage extends StatefulWidget {
    
    
  @override
  State<StatefulWidget> createState() => PageState();
}

class PageState extends State<AndroidPlatformPage> {
    
    
  static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
  static final String NATIVE_METHOD_ADD = "numberAdd"; //原生android平台定义的供flutter端唤起的方法名
  static final MethodChannel _MethodChannel = MethodChannel(METHOD_CHANNEL); //平台交互通道

  @override
  Widget build(BuildContext context) {
    
    
    return Scaffold(
      appBar: AppBar(
        title: Text("平台交互"),
        centerTitle: true,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          RaisedButton(
            color: Colors.orangeAccent,
            child: Text("计算两个数的和"),
            onPressed: () {
    
    
              getNumberResult(25, 36);
            },
          ),
        ],
      ),
    );
  }

 
  /**
   * 调用平台方法计算两个数的和,并调用原生toast打印出结果
   */
  void getNumberResult(int i, int j) async {
    
    
    Map<String, dynamic> map = {
    
    "number1": 12, "number2": 43};
    int result = await _MethodChannel.invokeMethod(NATIVE_METHOD_ADD, map);
    print("调用原生平台计算后的结果为:${result}");
  }
}

Passe parâmetros por MethodChannel e obtenha o valor de retorno. A lógica de execução de ambas as extremidades é exatamente a mesma. Seja chamando de volta os dados do lado Flutter para o lado Nativo ou o lado Nativo chamando de volta os dados do lado Flutter, ele é passado primeiro pelo lado evocado.Um é responsável por processar o retorno de chamada e o outro é
methodChannel.setMethodCallHandlerresponsável methodChannel.invokeMethod(String method, [ dynamic arguments ])por enviar eventos e transportar parâmetros.

2.1.1 Fim do recebimento e processamento de eventos

Ao receber e processar o retorno de chamada, as informações repassadas pelo remetente do evento são recebidas onMethodCall(MethodCall call, MethodChannel.Result result)por meio de methodCall e o resultado processado é enviado ao remetente do evento por meio de Result .

  • Use methodCall.method: para distinguir diferentes nomes de funções (métodos) para executar diferentes lógicas de negócios,
  • Pass methodCall.hasArgument("key"): Determine se existe um valor correspondente a uma determinada chave
  • Pass methodCall.argument("key"): Obtenha o valor correspondente à chave
  • Pass result.success(object): Retorna o resultado processado ao remetente do evento
2.1.2 Fim do envio do evento

O remetente do evento trata o evento passando methodChannel.invokeMethod("方法名","要传递的参数")os parâmetros que precisam ser passados ​​para o ouvinte do evento.
em

  • 方法名:Não pode estar vazio
  • 要传递的参数: pode estar vazio, se não estiver vazio, deve ser um objeto serializável Json.

Em seguida, o ouvinte setMethodCallHandlercompleta todo o processo de interação da plataforma executando operações relevantes, executando o processamento lógico correspondente nos parâmetros passados ​​e, em seguida, devolvendo os resultados.

No exemplo acima, o lado Flutter serve como remetente do evento, e o lado Nativo serve como lado de recebimento e processamento de eventos. Na verdade, o design do MethodChannel permite que as identidades dos dois sejam trocadas, ou seja, enviar mensagens de o lado nativo para o Flutter e depois obter os resultados de retorno. A lógica de implementação é a descrita acima. No processo reverso, em aplicativos de desenvolvimento reais, acredito que existem muito mais cenários de uso para enviar mensagens ativamente para o Flutter através do EventChannel do lado nativo do que usar o lado nativo para processar os dados de retorno do lado do Flutter por meio de retornos de chamada do MethodChannel , portanto, não vou entrar em detalhes sobre o lado nativo aqui. . Os leitores interessados ​​podem conferir o código de suporte deste blog para exemplos de código relevantes e interpretações de anotações. Vamos dar uma olhada no processo de operação específico de envio ativo de mensagens para o Flutter por meio do EventChannel.

2.2 O lado nativo usa EventChannel para enviar dados (mensagens) ativamente para o lado Flutter

Análise de cenário: Realize a transmissão ativa de dados do lado Nativo para o lado Flutter: Depois que a página for renderizada com sucesso, uma string é enviada do lado nativo para o lado Flutter e exibida no widget de texto do lado Flutter. Quando o botão é ativado a interface do Flutter é clicada, o método nativo é chamado. Envie mensagens ativamente para o Flutter e atualize a exibição da IU do lado final do Flutter.

renderizações
Native envia mensagens ativamente para Flutter

código lateral do Android

public class MainActivity extends FlutterActivity {
    
    
    private static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
    private static final String EVENT_CHANNEL = "com.zhuandian.flutter/android/event"; //事件通道,供原生主动调用flutter端使用
    private static final String METHOD_NATIVE_SEND_MESSAGE_FLUTTER = "nativeSendMessage2Flutter"; //原生主动向flutter发送消息
    private EventChannel.EventSink eventSink;
    private MethodChannel methodChannel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        GeneratedPluginRegistrant.registerWith(this);

        methodChannel = new MethodChannel(getFlutterView(), METHOD_CHANNEL);
        //接受fltuter端传递过来的方法,并做出响应逻辑处理
        methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
    
    
            @Override
            public void onMethodCall(MethodCall call, MethodChannel.Result result) {
    
    
                System.out.println(call.method);
                 if (call.method.equals(METHOD_NATIVE_SEND_MESSAGE_FLUTTER)) {
    
    
                    nativeSendMessage2Flutter();
                }
            }
        });


        new EventChannel(getFlutterView(), EVENT_CHANNEL).setStreamHandler(new EventChannel.StreamHandler() {
    
    
            @Override
            public void onListen(Object o, EventChannel.EventSink eventSink) {
    
    
                MainActivity.this.eventSink = eventSink;
                eventSink.success("事件通道准备就绪");
                //在此不建议做耗时操作,因为当onListen回调被触发后,在此注册当方法需要执行完毕才算结束回调函数
                //的执行,耗时操作可能会导致界面卡死,这里读者需注意!!
            }

            @Override
            public void onCancel(Object o) {
    
    

            }
        });


    }


    /**
     * 原生端向flutter主动发送消息;
     */
    private void nativeSendMessage2Flutter() {
    
    
        //主动向flutter发送一次更新后的数据
        eventSink.success("原生端向flutter主动发送消息");
    }
}

Código lateral flutuante

class AndroidPlatformPage extends StatefulWidget {
    
    
  @override
  State<StatefulWidget> createState() => PageState();
}

class PageState extends State<AndroidPlatformPage> {
    
    
  static final String METHOD_CHANNEL = "com.zhuandian.flutter/android";
  static final String EVENT_CHANNEL = "com.zhuandian.flutter/android/event";

  static final String NATIVE_SEND_MESSAGE_TO_FLUTTER =
      "nativeSendMessage2Flutter"; //原生主动向flutter发送消息

  static final MethodChannel _MethodChannel =
      MethodChannel(METHOD_CHANNEL); //平台交互通道
  static final EventChannel _EventChannel =
      EventChannel(EVENT_CHANNEL); //原生平台主动调用flutter端事件通道

  String _fromNativeInfo = "";

  @override
  void initState() {
    
    
    super.initState();
    _EventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onErroe);
  }
  

  /**
   * 监听原生传递回来的值(通过eventChannel)
   */
  void _onEvent(Object object) {
    
    
    print(object.toString() + "-------------从原生主动传递过来的值");
    setState(() {
    
    
      _fromNativeInfo = object.toString();
    });
  }

  void _onErroe(Object object) {
    
    
    print(object.toString() + "-------------从原生主动传递过来的值");
  }

  @override
  Widget build(BuildContext context) {
    
    
    return Scaffold(
      appBar: AppBar(
        title: Text("平台交互"),
        centerTitle: true,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Text("从原生平台主动传递回来的值"),
          Text(_fromNativeInfo),
          RaisedButton(
            color: Colors.orangeAccent,
            child: Text("点击调用原生主动向flutter发消息方法"),
            onPressed: () {
    
    
              _MethodChannel.invokeMethod(NATIVE_SEND_MESSAGE_TO_FLUTTER);
            },
          ),
        ],
      ),
    );
  }
}

Comparando a transferência de dados na forma de retornos de chamada do MethodChannle, combinada com o EventChannel enviando dados ativamente do lado nativo para o lado do Flutter, podemos descobrir que este último presta mais atenção ao monitoramento. Depois de registrarmos o objeto EventChannel no lado nativo , então o enviamos para o Flutter por meio do métodovoid success(Object var1) EventChannel.EventSink .data

No lado do Flutter, vinculamos o objeto de escuta durante a inicialização da página

@override
  void initState() {
    
    
    super.initState();
    _EventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onErroe);
  }

E _onEvento valor é enviado ativamente do nativo por meio do monitoramento, e então o processamento correspondente é registrado.

  /**
  * 监听原生传递回来的值(通过eventChannel)
  */
 void _onEvent(Object object) {
    
    
   print(object.toString() + "-------------从原生主动传递过来的值");
   setState(() {
    
    
     _fromNativeInfo = object.toString();
   });
 }

Devido a limitações de espaço, exibirei o código na renderização no início da postagem do blog e não explicarei os exemplos de código na renderização um por um. O código completo não possui comentários no código-fonte correspondente a este artigo. Leitores pode ler o código-fonte de suporte e combiná-lo com o código. Comentários para autoteste.
O código completo da parte de interação da plataforma:
Lado nativo: https://github.com/xiedong11/flutter_app/blob/master/android/app/src/main/java/com/zhuandian/flutterapp/MainActivity.java
Lado Flutter: https://github.com/xiedong11/flutter_app/blob/master/lib/pages/platform/android_platform_page.dart

Acho que você gosta

Origin blog.csdn.net/xieluoxixi/article/details/103048991
Recomendado
Clasificación