一、安装flutter

java的环境变量与android studio的安装与配置在此忽略,仅作为已有android项目添加集成flutter项目参考。

1、android studio安装flutter与dart插件

android studio的File->Settings->Plugins中搜索flutter与dart,然后install即可

flutter和java 怎么使用 flutter和java混合开发_移动开发


flutter和java 怎么使用 flutter和java混合开发_kotlin_02

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

flutter和java 怎么使用 flutter和java混合开发_android_03

打开cmd运行flutter doctor ,flutter会自动下载相关依赖

flutter和java 怎么使用 flutter和java混合开发_flutter和java 怎么使用_04


没有报错,就安装完成了

二、创建flutter项目并关联至native项目*

1、创建flutter项目

flutter和java 怎么使用 flutter和java混合开发_kotlin_05


flutter和java 怎么使用 flutter和java混合开发_kotlin_06

创建好了就这样

flutter和java 怎么使用 flutter和java混合开发_flutter_07

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和java 怎么使用 flutter和java混合开发_移动开发_08

编译完成后,就看到已经flutter项目已经导入进来了

flutter和java 怎么使用 flutter和java混合开发_flutter和java 怎么使用_09

在native项目下build文件中添加implementation project(’:flutter’)以导入flutter项目到native项目中。

flutter和java 怎么使用 flutter和java混合开发_flutter_10


同步完成后就可以运行了。

三、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

flutter和java 怎么使用 flutter和java混合开发_kotlin_11


2、android端添加FlutterBoost依赖

同步完成后在android的app->build.gradle->dependencies中添加FlutterBoost的依赖

implementation project(path: ':flutter_boost')

flutter和java 怎么使用 flutter和java混合开发_flutter_12

3、android 端FlutterBoost的使用
(1)在 AndroidManifest.xml 中添加配置

<!-- FlutterBoost 配置 -->
<meta-data
    android:name="flutterEmbedding"
    android:value="2" />

flutter和java 怎么使用 flutter和java混合开发_flutter和java 怎么使用_13


(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
        )
    );
  }
}

flutter和java 怎么使用 flutter和java混合开发_kotlin_14


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端打印结果

flutter和java 怎么使用 flutter和java混合开发_android_15


(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代码的混合开发就可以做基本跳转及交互了。
没怎么写博客,写的不好多多理解,有问题可以留言沟通。