一.Android已有项目接入Flutter module(官方提供的module方式)

官方文档:https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

1.创建Flutter module

(1)在已有的flutter项目中 输入命令:flutter create -t module moduleName,将生成的module复制到原生项目中
(2)或者在已有Android项目中输入上面命令,同样会生成一个module

2.在Android项目工程的settings.gradle增加以下配置

setBinding(new Binding([gradle: this]))evaluate(new File(        settingsDir.parentFile,        'AndroidFlutterProject/flutter_module/.android/include_flutter.groovy'))

flutter_module和app是同一级
AndroidFlutterProject:是Android项目的工程名
flutter_module:是刚才通过命令生成的module

3.在app的build.gradle增加以下依赖

implementation project(':flutter')

注意:原生项目中minSdkVersion 至少为16,否则编译不过

通过以上三步就将Flutter集成到原生项目中了。

二:Android原生调Flutter代码

Flutter提供两种引入方法:一个是View,会默认生成一个View,一个是FlutterFragment方式。
View方式:可以自己设置新View的大小,位置

FlutterView flutterView = Flutter.createView(this, getLifecycle(), "路由信息,自己自定义");FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(100, 100);layout.leftMargin = 0;layout.topMargin = 0;addContentView(flutterView, layout);

FlutterFragment方式:

setContentView(R.layout.activity_main);FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();fragmentTransaction.replace(R.id.fl_flutter_view, Flutter.createFragment("路由信息,自己自定义"));fragmentTransaction.commit();

通过以上任意一种方式,都会调用fluttermodule中lib包下main.dart这个文件,我们可以在这个文件下面配置路由信息,控制页面跳转展示。

void main() => runApp(widgetForRoute(window.defaultRouteName));Widget widgetForRoute(String route) {  switch (route) {    case '路由信息,自己自定义':      return Center(        child: Text('route: $route', textDirection: TextDirection.ltr),      );      return Center(        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),      );  }}

三:Flutter调用Android原生代码

Flutter调用原生主要使用插件方式,通过MethodChannel的方式。

1.在Application onCreate方法中进行初始化,关键

FlutterMain.startInitialization(this);

2.实现插件,创建一个类实现MethodChannel.MethodCallHandler,在onMethodCall回调方法中对Flutter指令分发处理。

public class FlutterPluginJumpToAct implements MethodChannel.MethodCallHandler {    //channel信息,可以自己随便定义    public static String CHANNEL = "com.qyh.jump/plugin";    static MethodChannel channel;    private Activity activity;    private FlutterPluginJumpToAct(Activity activity) {        this.activity = activity;    }    // 此方法需要外界进行调用注册    public static void registerWith(PluginRegistry.Registrar registrar) {        channel = new MethodChannel(registrar.messenger(), CHANNEL);        FlutterPluginJumpToAct instance = new FlutterPluginJumpToAct(registrar.activity());        //setMethodCallHandler在此通道上接收方法调用的回调        channel.setMethodCallHandler(instance);    }    @Override    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {        //通过methodCall可以获得参数和方法名,原生这面做对应业务        //result可以给Flutter设置回调        // "test1":是Flutter代码设置的调用指令        if (methodCall.method.equals("test1")) {            // do something            result.success("suc");        }    }}

3.在Activity中注册,此Activity需要继承FlutterActivity

public class MainActivity extends FlutterActivity  {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        GeneratedPluginRegistrant.registerWith(this);        registerCustomPlugin(this);    }    private static void registerCustomPlugin(PluginRegistry registrar) {        FlutterPluginJumpToAct.registerWith(registrar.registrarFor(FlutterPluginJumpToAct.CHANNEL));    }}

FlutterActivity继承的是Activity,如果想用其他Activity,比如AppCompatActivity,我们可以创建抽象Base类,继承AppCompatActivity实现FlutterView.Provider, PluginRegistry, FlutterActivityDelegate.ViewFactory一系列方法。然后让我们的Activity直接继承这个基类就可以了。

4.在Flutter代码中实现跳转逻辑编写

void main() => runApp(widgetForRoute(window.defaultRouteName));Widget widgetForRoute(String route) {    // com.qyh.jump/plugin是原生代码中定义好的,要对应起来  const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');  //test1 就是我们Flutter代码回调原生的指令名字  jumpPlugin.invokeMethod('test1');}

当Flutter代码执行到widgetForRoute(),会回调到插件FlutterPluginJumpToAct类的onMethodCall回调方法中,我们就可以通过methodCall.method获取到指令(test1)名,进行原生逻辑编写了,以上步骤就是Flutter调用原生代码的方法。

4.1.在Flutter代码中给原生传递参数
Flutter代码中通过Map的方式对数据进行拼接,然后回传给原生

void main() => runApp(widgetForRoute(window.defaultRouteName));Widget widgetForRoute(String route) {  // com.qyh.jump/plugin是原生代码中定义好的,要对应起来  const jumpPlugin = const MethodChannel('com.qyh.jump/plugin');  Map mapData = {"flutterKey1": "flutterValue1","flutterKey2": "flutterValue2"};  jumpPlugin.invokeMethod('test1',mapData);}

原生代码中通过methodCall.arguments获取,解析

@Overridepublic void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {    //通过methodCall可以获得参数和方法名,原生这面做对应业务    if (methodCall.method.equals("test1")) {        if (methodCall.arguments != null) {            Map arguments = (Map) methodCall.arguments;        }    }}

以上就是Android原生跟Flutter交互方式,在实际项目中我遇到一个实际问题,原生、Flutter混合开发会遇到栈混乱的情况,之后引入阿里的[flutter_boost] (https://github.com/alibaba/flutter_boost),详细接入可以参考开源库,下面总结一下我接入这个库遇到一些问题:

1.Android appcation中不能引用FlutterBoostPlugin
在原生项目 app下面gradle引入flutter_boost

implementation project(':flutter_boost')

2.v4 v7库版本冲突
将xservice_kit 、flutter_boost、 flutter_module、 app下gradle里版本统一。

3.Android接收Flutter中传参中文字符串乱码

String decodeValue = URLDecoder.decode(value, "UTF-8");

四、接入Flutter后调试问题

1.Android原生代码不能快速debug
解决方法:将Android Studio升级到最新版本,目前最新版本3.4.1

2.Flutter热加载
在flutter_module目录下 输入命令 flutter attach,这个时候会提示等待连接设备,然后 Run一次项目,当项目重新运行起来后,就可以在Terminal 中输入r(热加载)、R(热重启)命令进行愉快的开发了。

更多相关文章

  1. 移动网站开发中常用的10段JavaScript代码
  2. 准备一个rubymotion for android的实际项目
  3. android 开发中判断网络是否连接的代码
  4. 整理 酷炫 Android(安卓)开源UI框架 表格
  5. 成为更好的Android开发者前,我们需要注意的31个细节
  6. android:打开Eclipse之后android项目都报错怎么解决
  7. Android(安卓)ListView 去除边缘阴影、选中色、拖动背景色等
  8. MVVM模式开源学习项目——玩Android客户端
  9. 关于listView.setAdapter(adapter)报空指针异常的问题

随机推荐

  1. 滴滴敏捷数据中台实践
  2. 基于HBase和Spark构建企业级数据处理平台
  3. 阿里云Redis技术架构演进
  4. 记一次线上问题排查与解决
  5. Pythoner 的花式浪漫,你会吗?
  6. 一起来用 Python 做个是男人就坚持100秒
  7. js之数组对象与访问器
  8. 华盛顿大学推出YOLOv3:检测速度比SSD和Ret
  9. 伯克利RISELab推出免费在线课程,涵盖数据
  10. 为什么深度学习没有取代传统的计算机视觉