Flutter笔记

Posted 火山石

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter笔记相关的知识,希望对你有一定的参考价值。

一、Android 集成 Flutter 实现流程
闲鱼、头条 在 android 集成 Flutter 模块都有自己的实现方案:闲鱼团队方案 & 头条团队方案

我们以官方方案方式为主。

一、Android 集成 Flutter 实现流程
闲鱼、头条 在 Android 集成 Flutter 模块都有自己的实现方案:闲鱼团队方案 & 头条团队方案

我们以官方方案方式为主。

(1)创建 flutter module 模块

         官方提供了如下命令,用来创建 flutter module:

flutter create -t module flutter_module (module名称)
(2)将 flutter module 模块添加到当前项目

          打开项目根目录的 settings.gradle 文件,添加如下代码片段:

setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        "flutter_in_android/.android/include_flutter.groovy"
))
          打开 app / build.gradle 文件,在 dependencies 下添加 flutter 依赖:

dependencies
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
 
    ......
 
    implementation project(':flutter')

以上配置完成后,Flutter就已经集成在当前Android工程项目中了。

二、Flutter 视图界面展示
Flutter的视图展示有两种实现方式:

(1)创建 FlutterView 视图组件,以 View 的方式添加到当前原生视图布局

          官方依赖库中提供了 createView 的方法,方便开发者快速创建 Flutter 视图组件,并嵌入在当前原生布局:

/**
 * 此 Activity 中向 Flutter 端发送消息
 * create by Songlcy 2019-02-15
 */
public class FlutterContainerActy extends AppCompatActivity
 
    private ViewGroup.LayoutParams layoutParams;
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState)
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_flutter);
        // 1. 通过Flutter.createView创建FlutterView组件方式
        FlutterView flutterView = Flutter.createView(this, getLifecycle(), "flutterView");
        layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        // 2. 将Flutter 视图添加到原生布局中
        addContentView(flutterView, layoutParams);
   

上述代码中,我们通过 Flutter.createView 创建 Flutter 视图组件 FlutterView,createView方法接收三个参数

 @NonNull final Activity activity: Activity实例
@NonNull final Lifecycle lifecycle: 定义具有Android生命周期的对象
final String initialRoute: 初始化的视图路由名称
所以我们可以根据 initialRoute 来动态加载不同的 Flutter 视图组件:

import 'dart:ui'; // 引入后可以使用window对象
 
@override
Widget build(BuildContext context)
  switch(window.defaultRouteName)
 
    case "flutterView":     
        return Scaffold(...);
 
    ......
 
    default:
      return Center(
        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
      );
 

(2)启动 FlutterActivity 界面

在很多场景下,我们需要从原生界面跳转到Flutter视图界面,所以我们可以直接启动FlutterActivity来实现:

Intent intent = new Intent(MainActivity.this, FlutterActy.class);
startActivity(intent);
三、Android 与 Flutter 通信方式
React Native跨平台开发框架是通过 RCTBatchedBridge 实现 js 与 Native 的交互,Flutter与Native的通信机制与RN的实现比较相似,只是没有了Bridge的桥接层,通过Channel直接与原生交互。官方在Channel通信的实现上同样采用了以字符串为唯一协议的方式,来同时构建通信交互信号。实现的具体方式和RN也同样类似,Native | Flutter 端实现监听回调,注册即可。

(1)MethodChannel

         使用场景:Flutter端向Native端发送通知

         实现方式:

Native端

new MethodChannel(getFlutterView(), "com.xxx").setMethodCallHandler(new MethodChannel.MethodCallHandler()
    @Override
    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result)
        // methodCall.method 对应 Flutter端invokeMethod方法的第一个参数
        if(methodCall.method.equals("123"))
            // 获取Flutter传递的参数
            String msg = methodCall.<String>argument("msg");
            // 回传给Flutter
            result.success(msg);
       
   
);
上述代码中我们创建了MethodChannel实例,并调用 setMethodCallHandler 注册监听回调。从源码中,可以看到MethodChannel构造函数接收两个参数

public MethodChannel(BinaryMessenger messenger, String name)
     this(messenger, name, StandardMethodCodec.INSTANCE);

 
public MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec)
 ......

name 就是双发通信的唯一标识,我们可以简单理解为钥匙即可。

MethodCodec有两种实现:

JSONMethodCodec

JSONMethodCodec的编解码依赖于JSONMessageCodec,当其在编码MethodCall时,会先将MethodCall转化为字典"method":method,"args":args。其在编码调用结果时,会将其转化为一个数组,调用成功为[result],调用失败为[code,message,detail]。再使用JSONMessageCodec将字典或数组转化为二进制数据。

StandardMethodCodec

MethodCodec的默认实现,StandardMethodCodec的编解码依赖于StandardMessageCodec,当其编码MethodCall时,会将method和args依次使用StandardMessageCodec编码,写入二进制数据容器。其在编码方法的调用结果时,若调用成功,会先向二进制数据容器写入数值0(代表调用成功),再写入StandardMessageCodec编码后的result。而调用失败,则先向容器写入数据1(代表调用失败),再依次写入StandardMessageCodec编码后的code,message和detail。

Flutter端

import 'package:flutter/services.dart';
 
static const methodPlugin = const MethodChannel('com.xxx');
String callbackResult = await methodPlugin.invokeMethod('123', "msg": "456" );
在Flutter同样需要创建MethodChannel实例,并将通信钥匙作为参数传入,要与原生端保持一致。然后调用invokeMethod方法向原生端发送通信请求。第一个参数表示要调用原生端的哪个方法,第二个参数为可选参数,即传递给Native端的数据参数。

(2)EventChannel

         使用场景:Native端向Flutter端发送通知

         实现方式:

Native端

new EventChannel(getFlutterView(), "com.xxx").setStreamHandler(new EventChannel.StreamHandler()
 
    @Override
    public void onListen(Object o, EventChannel.EventSink eventSink)
        eventSink.success("msg");
   
 
    @Override
    public void onCancel(Object o)
        // 做一些注销操作
   
);
和 MethodChannel 类似,EventChannel 也是通过 new 创建对象实例,并设置 StreamHandler 类型的监听回调。其中 onCancel 代表对面不再接收,这里我们可以做注销的逻辑操作。onListen 代表通信已经建立完毕,Native可以向Flutter发送数据。onListen 方法中携带了 EventSink 参数,后续Native发送数据都是经过 EventSink 的 success、error 方法。

Flutter端

import 'package:flutter/services.dart';
 
static const eventPlugin = const EventChannel('com.xxx');
 
@override
void initState()
  super.initState();
  _streamSubscription = eventPlugin.receiveBroadcastStream()
      .listen(_onData, onError: _onError, onDone: _onDone, cancelOnError: true);

 
void _onData(Object event)
  // 接收数据
  setState(()
    eventVal = event;
  );

 
void _onError(Object error)
  // 发生错误时被回调
  setState(()
    eventVal = "错误";
  );

 
void _onDone()
  //结束时调用

 
@override
void dispose()
  super.dispose();
  if(_streamSubscription != null)
    _streamSubscription.cancel();
 

同样与 MethodChannel 类似,首先是创建 EventChannel 实例,然后在 initState 生命周期中调用 receiveBroadcastStream方法的listen。listen 返回的是 StreamSubscription 对象。此处有点类似Android中的BroadcastReceiver广播。listen方法源码如下:

StreamSubscription<T> listen(void onData(T event),
      Function onError, void onDone(), bool cancelOnError);
可以看到,onData 为必需参数,onError、onDone、cancelOnError 为可选。顾名思义,onData 即为收到原生端发送数据的回调,onError为接收数据失败,onDone为接收数据结束,cancelOnError是一个bool类型参数,标识在发生错误时,时候自动取消通信。以上即可实现Native端向Flutter发送通知。

总结
Platform Channel 作为原生端与 Flutter 端建立通信渠道的方式,在混合开发模式中起到了至关重要的作用,很多地方都会涉及,例如编写 Plugin 等等。不仅能够帮助我们更深入的了解 Flutter 与 Native 之间的交互流程,在性能优化、问题分析上都可以得到延伸。
--------------------- 
作者:Songlcy 
来源:CSDN 
原文:https://blog.csdn.net/u013718120/article/details/86679147 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

以上是关于Flutter笔记的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 布局- ListBodyListViewCustomMultiChildLayout详解

Flutter 布局- FlowTableWrap详解

Flutter入门这一篇效率文章就够了

[Flutter插件开发] 网络状态监听组件

Flutter:每个flutter命令都会出现这个错误

使用Timer实现Flutter启动页