一、安装flutter
java的环境变量与android studio的安装与配置在此忽略,仅作为已有android项目添加集成flutter项目参考。
1、android studio安装flutter与dart插件
android studio的File->Settings->Plugins中搜索flutter与dart,然后install即可
2、下载flutterSDK
去flutter官网下载其最新可用的安装包,点击下载 ;
注意,Flutter的渠道版本会不停变动,请以Flutter官网为准。另外,在中国大陆地区,要想正常获取安装包列表或下载安装包,可能需要翻墙,读者也可以去Flutter github项目下去下载安装包 。
将安装包zip解压到你想安装Flutter SDK的路径(如:C:\src\flutter;注意,不要将flutter安装到需要一些高权限的路径如C:\Program Files\)。
在Flutter安装目录的flutter文件下找到flutter_console.bat,双击运行并启动flutter命令行,接下来,你就可以在Flutter命令行运行flutter命令了。
3、配置flutter环境变量
如果想在命令行中使用 flutter 命令,你需要添加flutter的路径到path中去。这个和配置java环境变量是同样的做法,找到flutter安装路径,比如我的是xx\flutter\bin,我复制这个路径,右键我的电脑–>属性–>高级系统属性–>环境变量–>找到PATH,点击编辑–>在最后把刚复制的路径粘贴进来,–>一直保存确定就可以了。
继续添加flutter的国内镜像,避免后续需要翻墙下载资源,直接添加到系统变量就行。
FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn
PUB_HOSTED_URL: https://pub.flutter-io.cn
打开cmd运行flutter doctor ,flutter会自动下载相关依赖
没有报错,就安装完成了
二、创建flutter项目并关联至native项目*
1、创建flutter项目
创建好了就这样
2、把这个flutter项目关联到native项目
首先在android项目的settings.gradle文件中添加如下代码,然后点击Sync。
include ':flutter_module'
setBinding(new Binding([gradle: this]))
evaluate(new File(
settingsDir.parentFile,
'AndroidDemo/flutter_module/.android/include_flutter.groovy'))
编译完成后,就看到已经flutter项目已经导入进来了
在native项目下build文件中添加implementation project(’:flutter’)以导入flutter项目到native项目中。
同步完成后就可以运行了。
三、android与flutter交互**
我这里选择FlutterBoost ,这是阿里系闲鱼技术团队开源的 Flutter 插件,它可以轻松为现有原生应用程序提供 Flutter 混合集成方案。其理念是将 Flutter 像 WebView 那样来使用。FlutterBoost 帮开发者处理 Native 与 Flutter 页面的映射和跳转,开发者只需关心页面的名字和参数即可 ( 通常可以是 URL ) 。由于FlutterBoost不一定支持最新Flutter版本,关于Flutter安装版本,自行查看FlutterBoost当前支持版本。
关于FlutterBoost的使用,我参考的大佬博客,查看原文章 1、flutter添加依赖
在根目录 pubspec.yaml 文件中的 dependencies : 下添加 FlutterBoost 依赖并点击Pub get。
flutter_boost: 1.12.13
2、android端添加FlutterBoost依赖
同步完成后在android的app->build.gradle->dependencies中添加FlutterBoost的依赖
implementation project(path: ':flutter_boost')
3、android 端FlutterBoost的使用
(1)在 AndroidManifest.xml 中添加配置
<!-- FlutterBoost 配置 -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
(2)添加路由配置PageRouter
class PageRouter {
val pageName: HashMap<String?, String?> = object : HashMap<String?, String?>() {
init {
put("first", "first")
put("second", "second")
put("tab", "tab")
put("sample://flutterPage", "flutterPage")
}
}
val FLUTTER_PAGE_MAIN = "sample://firstPage"
val NATIVE_PAGE_URL = "sample://nativePage"
val FLUTTER_PAGE_URL = "sample://flutterPage"
val FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage"
fun openPageByUrl(context: Context, url: String, params: Map<*, *>): Boolean {
return openPageByUrl(context, url, params as HashMap<String?, Any?>, 0)
}
fun openPageByUrl(
context: Context,
url: String,
params: HashMap<String?, Any?>,
requestCode: Int
): Boolean {
val path = url.split("\?".toRegex()).toTypedArray()[0]
Log.i("openPageByUrl", path)
return false
}
}
(2)自定义 Application ,并在 onCreate 方法中初始化 FlutterBoost
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
//引擎生命周期监听
val boostLifecycleListener = object : FlutterBoost.BoostLifecycleListener {
override fun onEngineCreated() {
//引擎创建成功
}
override fun onPluginsRegistered() {
//插件注册
}
override fun beforeCreateEngine() {
//创建引擎前
}
override fun onEngineDestroy() {
//引擎被销毁
}
}
//路由跳转监听
val router = INativeRouter { context, url, urlParams, requestCode, exts ->
//当 Flutter 中使用 FlutterBoost 启动新页面 (Flutter/Native) 时,触发该回调
PageRouter().openPageByUrl(context, url,
urlParams as HashMap<String?, Any?>, requestCode)
}
//
// AndroidManifest.xml 中必须要添加 flutterEmbedding 版本设置
//
// <meta-data android:name="flutterEmbedding"
// android:value="2">
// </meta-data>
//
val platform = FlutterBoost.ConfigBuilder(this, router)
.isDebug(true)
.whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED)
.renderMode(FlutterView.RenderMode.texture)
.lifecycleListener(boostLifecycleListener)
.build()
FlutterBoost.instance().init(platform)
}
}
(3)在页面中写个按钮,实现native跳转到flutter页面
findViewById<TextView>(R.id.tv_to_flutter).setOnClickListener {
val params = BoostFlutterActivity.SerializableMap().map
val intent =
BoostFlutterActivity.withNewEngine().url("firstPage")
.params(params)
.backgroundMode(BoostFlutterActivity.BackgroundMode.opaque)
.build(this)
startActivity(intent)
}
注册BoostFlutterActivity到AndroidManifest.xml
<activity android:name="com.idlefish.flutterboost.containers.BoostFlutterActivity"/>
(4)在flutter中初始化FlutterBoost
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_module/one_page.dart';
import 'package:flutter_module/two_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
FlutterBoost.singleton.registerPageBuilders({
'firstPage': (pageName, params, _) => OnePage(params: params,),
'secondPage': (pageName, params, _) => TwoPage(),
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Boost example',
builder: FlutterBoost.init(),
debugShowCheckedModeBanner: false,
theme: ThemeData(
platform: TargetPlatform.iOS, // 使页面跳转时从左至右滑动
),
home: Container(
color: Colors.white
)
);
}
}
OnePage.dart
import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
class OnePage extends StatefulWidget {
dynamic params;
OnePage({Key key,this.params}) : super(key:key);
@override
_OnePageState createState() => _OnePageState();
}
class _OnePageState extends State<OnePage> {
@override
void initState() {
// TODO: implement initState
super.initState();
print("参数");
print(widget.params);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: InkWell(
child: Text('这是 One 页面,点击可以跳转回android页面'),
onTap: (){
print("点击");
FlutterBoost.singleton.open("sample://nativePage", urlParams: <dynamic,dynamic>{
"query": {"aaa": "bbb"},
"params":"参数2"
});
},
),
),
);
}
}
到此就可以运行了,android也能跳转到flutter的页面。
4、传参
(1)android端传参
findViewById<TextView>(R.id.tv_to_flutter).setOnClickListener {
var requestParams: MutableMap<String, Any>? = null
var params = requestParams ?: mutableMapOf()
params.put("test1","这是参数1")
params.put("test2","这是参数2")
val intent =
BoostFlutterActivity.withNewEngine().url("firstPage")
.params(params)
.backgroundMode(BoostFlutterActivity.BackgroundMode.opaque)
.build(this)
startActivity(intent)
}
Flutter端打印结果
(2)android 端接收参数并跳转到native界面
在PageRouter的openPageByUrl方法中处理,完整PageRouter:
class PageRouter {
val pageName: HashMap<String?, String?> = object : HashMap<String?, String?>() {
init {
put("first", "first")
put("second", "second")
put("tab", "tab")
put("sample://flutterPage", "flutterPage")
}
}
val FLUTTER_PAGE_MAIN = "sample://firstPage"
val NATIVE_PAGE_URL = "sample://nativePage"
val FLUTTER_PAGE_URL = "sample://flutterPage"
val FLUTTER_FRAGMENT_PAGE_URL = "sample://flutterFragmentPage"
fun openPageByUrl(context: Context, url: String, params: Map<*, *>): Boolean {
return openPageByUrl(context, url, params as HashMap<String?, Any?>, 0)
}
fun openPageByUrl(
context: Context,
url: String,
params: HashMap<String?, Any?>,
requestCode: Int
): Boolean {
val path = url.split("\?".toRegex()).toTypedArray()[0]
Log.i("openPageByUrl", path)
return try {
if (pageName.containsKey(path)) {
val intent = BoostFlutterActivity.withNewEngine().url(pageName.get(path)!!)
.params(params)
.backgroundMode(BoostFlutterActivity.BackgroundMode.opaque).build(context)
if (context is Activity) {
context.startActivityForResult(intent, requestCode)
} else {
context.startActivity(intent)
}
return true
} else if (url.startsWith(NATIVE_PAGE_URL)) {
for ((key, value) in params) {
println("方式一: 获取传参Key = $key ---- Value = $value")
}
context.startActivity(Intent(context, NativePageActivity::class.java))
return true
}
false
} catch (t: Throwable) {
false
}
}
}
到此,android中集成flutter代码的混合开发就可以做基本跳转及交互了。
没怎么写博客,写的不好多多理解,有问题可以留言沟通。