zhaobinglong / myBlog

https://zhaobinglong.github.io/myBlog/
MIT License
7 stars 0 forks source link

flutter之数据通信 #81

Open zhaobinglong opened 3 years ago

zhaobinglong commented 3 years ago

flutter和原生native通信

应用的Flutter部分通过平台通道(platform channel)将消息发送到其应用程序的所在的宿主(iOS或Android)应用(原生应用)。宿主监听平台通道,并接收该消息。然后它会调用该平台的API,并将响应发送回客户端,即应用程序的Flutter部分。

BinaryMessenger是Platform端与Flutter端通信的工具,其通信使用的消息格式为二进制格式数据。当我们初始化一个Channel,并向该Channel注册处理消息的Handler时,实际上会生成一个与之对应的BinaryMessageHandler,并以channel name为key,注册到BinaryMessenger中。当Flutter端发送消息到BinaryMessenger时,BinaryMessenger会根据其入参channel找到对应的BinaryMessageHandler,并交由其处理。

平台通道(platform channel)

通道配置参数

name: String类型,代表Channel的名字,也是其唯一标识符。 messager:BinaryMessenger类型,代表消息信使,是消息的发送与接收的工具。 codec: MessageCodec类型或MethodCodec类型,代表消息的编解码器。

MethodChannel

由 flutter 发起作为 client 方,native 接收作为 server 方,并能进行消息回传

class FlutterPlugin {
  ///指定channel名称
  static const MethodChannel _channel = const MethodChannel('flutter_plugin');

  ///发送消息
  static Future<String> showToast({String msg}) async {
    String result = await _channel.invokeMethod('toast',{"msg":msg});
    return result;
  }
}

1.渠道名: flutter_plugin
2.方法名: toast
3.参数: {"msg":msg}  参数必须以键值对的方式发送
4.result结果,原生回传消息
zhaobinglong commented 3 years ago

dio(flutter与API通信的库)

dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等...

封装一个dio实例

import 'package:dio/dio.dart';
import 'package:gank_flutter/utils/LogUtils.dart';

class HttpUtils {
  static const BASE_URL = "http://gank.io/api";
  static const CONNECT_TIMEOUT = 5000;
  static const RECEIVE_TIMEOUT = 3000;
  static Dio dio;

  /// 生成Dio实例
  static Dio getInstance() {
    if (dio == null) {
      //通过传递一个 `BaseOptions`来创建dio实例
      var options = BaseOptions(
          baseUrl: BASE_URL,
          connectTimeout: CONNECT_TIMEOUT,
          receiveTimeout: RECEIVE_TIMEOUT);
      dio = new Dio(options);
    }
    return dio;
  }

  /// 请求api
  static Future<Map> request(String url, {data, method}) async {
    data = data ?? {};
    method = method ?? "get";

    // 由于我示例的接口是 http://gank.io/api/data/福利/10/1
    // 所以使用下面这张方式拼接get参数
    // 如上面则为 http://gank.io/api/data/:category/:pageSize/:page
    data.forEach((key, value) {
      if (url.indexOf(key) != -1) {
        url = url.replaceAll(':$key', value.toString());
      }
    });
    // 打印请求相关信息:请求地址、请求方式、请求参数
    LogUtils.log("请求地址:【$method $url】");
    LogUtils.log("请求参数:【$data】");

    var dio = getInstance();
    var res;
    if (method == "get") {
      // get
      var response = await dio.get(url);
      res = response.data;
    } else {
      // post
      var response = await dio.post(url, data: data);
      res = response.data;
    }
    return res;
  }

  /// get
  static Future<Map> get(url, data) => request(url, data: data);

  /// post
  static Future<Map> post(url, data) =>
      request(url, data: data, method: "post");
}

泛型问题

zhaobinglong commented 3 years ago

组件通信

父页面向子组件传值

父页面实例化子组件,给子组件传递参数和方法,子组件可以通过方法调用父页面函数,常见场景是子组件通知父页面刷新

new childTwo(dataTwo: dataTwo,callBack: (value)=>onChanged(value)),

// 子组件接受参数
class childTwo extends StatefulWidget {
  childTwo({Key key, this.dataTwo, this.callBack}) : super(key: key);
  final callBack;
  String dataTwo;

组件和组件通信eventBus

EventBus是全局事件总线,底层通过Stream来实现;它可以实现不同页面的跨层访问,通过Stream的机制来实现不同widget之间的状态共享。EventBus对象初始化实际上初始化了一个_streamController对象,而这个对象是通过StreamController的broadcast(sync: sync)方法初始化的,这里大致可以看出来,EventBus的底层实际上就是通过Stream来实现的.这里默认带了sync参数,表示是否同步,默认为async.

// 在bus中注册事件
import 'package:event_bus/event_bus.dart';
EventBus eventBus = new EventBus();
class TransEvent{
  String text;
  TransEvent(this.text);
}

// 监听事件
 eventBus.on<TransEvent>().listen((TransEvent data) => show(data.text));

// 触发事件
eventBus.fire(new TransEvent('$inputText'));

参考

https://www.jianshu.com/p/b16ecd3bfaa1