原生项目集成Flutter

  1. 创建Flutter module
  2. 添加Flutter module依赖
  3. 在Java/Object-c中调用Flutter module
  4. 编写Dart代码
1.创建FlutterModule

首先在你的Native项目的上一级目录,运行如下代码

flutter create -t module flutter_module

这样,就会创建一个flutter模块

flutter 混合开发android 打包 flutter native混合开发_热加载


我们进入flutter_module,可以发现包含.android.ios,这两个文件夹是隐藏文件,也是这个flutter_module宿主工程

  • .android - flutter_module的Android宿主工程
  • .ios - flutter_module的IOS宿主工程
  • lib - flutter_module的Dart部分的代码
  • pubspec.yaml - flutter_module的项目依赖配置文件

因为宿主工程的存在,我们这个flutter_module在不加额外的配置的情况下是可以独立运行的。通过安装了Flutter与Dart插件的Android Studio打开这个flutter_module项目,通过运行按钮是可以直接运行它的

2.添加Flutter module依赖

在我们的原生Android项目的settings.gradle中添加如下代码
这一步是引用flutter工程,添加之后Binding会报红,这个地方不管他

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

然后在app的build.gradle中,添加

dependencies {
	//...
	implementation project(":flutter")
}

Android项目minSdkVersion最低需为16
Android项目需配置使用1.8进行编译 (sourceCompatibility和targetCompatibility)

3.在Java中调用Flutter module
使用Flutter.createView API的方式
View flutterView = Flutter.createView(MainActivity.this, getLifecycle(), "route1");
    FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(600, 800);
    layout.leftMargin = 100;
    layout.rightMargin = 200;
    addContentView(flutterView, layout);
使用FlutterFragment的方式
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.layout_container, Flutter.createFragment("route1"));
tx.commit();

上面我们使用字符串"route1"来告诉Dart代码在Flutter视图中显示哪个小部件。
Flutter模块项目的lib/main.dart文件需要通过window.defaultRouteName来获取Native指定要显示的路由名,以确定要创建哪个窗口小部件并传递给runApp;

4.编写Dart代码
import 'package:flutter/material.dart';
import 'dart:ui';

void main() => runApp(MyApp(initParams : window.defaultRouteName));

class MyApp extends StatelessWidget {
  final String initParams;


  const MyApp({Key key,this.initParams}):super(key:key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page',initParams:initParams),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title,this.initParams}) : super(key: key);

  final String title;
  final String initParams;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'initParams:${widget.initParams}',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

运行Android项目,点击FLUTTER FRAGMENT按钮,可以看到

flutter 混合开发android 打包 flutter native混合开发_混合开发_02

无论是使用Flutter.createView的方式还是通过Flutter.createFragment的方式,都允许我们在加载Flutter module时传递一个String类型的initialRoute参数,该参数是用作路由名的,但也可以传递相传的其他的参数,比如json类型的数据。

混合开发进行热重启/热加载

我们在开发纯Flutter项目的时候,带有热重启/热加载的功能,但在混合开发的集成了Flutter的Android项目中,需要进行额外的操作。

  • 打开一个模拟器,或链接一个设备到电脑上
  • 关闭我们的APP,然后运行Flutter attach
cd flutter_module
	flutter attach

如果你连接了多个设备,flutter attach会提示你选择一个设备,需要使用flutter attach -d 来指定一个设备

然后运行Android项目,并执行了Flutter相关的功能,会在控制台打印如下的信息

flutter 混合开发android 打包 flutter native混合开发_混合开发_03

如果是热加载,按r
如果是热重启,按R
如果想请求帮助,按h
如果想退出,按q

接着,就可以再Flutter工程中修改代码了, 修改完毕后,按r就执行了热加载

调试Dart代码

混合开发的模式下,如何调试代码

  • 关闭App (很关键)
  • 点击AS的Flutter Attach按钮 (首先需要安装Flutter和Dart插件)
  • 启动App

    接下来就可以像调试普通Flutter项目一样来调试混合开发模式下的Dart代码了

运行Android工程时一定要再Android模式下的Android Studio中运行,因为Flutter模式下的Android Studio运行的是.android中的Android工程