一.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. 【Android学习笔记】AutoCompleteTextView(数组在代码中)
  2. Android 高通代码预制apk可卸载,恢复出厂设置apk可恢复 Android M
  3. 移动网站开发中常用的10段JavaScript代码
  4. android DPI与分辨率的关系及计算方式
  5. android:打开Eclipse之后android项目都报错怎么解决
  6. MVVM模式开源学习项目——玩Android客户端
  7. Android的布局管理器与java中的实现方式不同
  8. Android 系统服务的两种注册方式

随机推荐

  1. 了解 uri, content provide,包括 data and
  2. 【Android】数据存储之SQLite
  3. Android关于LinearLayout和RelativeLayou
  4. Android的介绍
  5. 百度招聘Android客服端(1)
  6. 在Android(安卓)studio中建立Java工程
  7. android与tomcat服务器交互实例
  8. android Service Activity三种交互方式(付
  9. 【进阶篇】Android学习笔记——TextInput
  10. Android官方命令深入分析之AVD Manager