不得不看的Flutter与Android混合开发

虽说flutter能够跨平台,但由于现在几乎都是现成的项目,所以目前几乎都是采用native+flutter的混合开发方案。那么该方案该如何实现尼?

1、flutter模块的导入

首先,切换到native项目的根目录的上一级目录。以笔者项目为例,路径为D:\FlutterHybrid\FlutterHybridAndroid,然后通过命令cd ../切换到上一级目录。再执行下面命令来创建一个flutter模块。

javascript 复制代码
    flutter create -t module flutter_module

上面的flutter_module就是我们创建的flutter模块名称。

当flutter模块创建成功后,我们就需要通过以下步骤来导入该模块。

1. 首先在在settings.gradle文件中添加如下代码。

javascript 复制代码
```
    setBinding(new Binding([gradle:this]))
    evaluate(new File(
            settingsDir.parentFile,'flutter_module/.android/include_flutter.groovy'
    ))
```

添加完成后,就能够在Android Studio中看到flutter模块,如下图。

2. 其次,在能够正确显示flutter模块后,我们就需要通过implementation project(':flutter')来导入该模块。添加成功后就开始编译项目,这时候就可能会遇到如下错误。

这就是我们需要注意的一点,native项目的minSdkVersion不能小于Flutter模块的minSdkVersion 。解决方案就是把native项目的minSdkVersion的值修改为大于flutter模块的minSdkVersion的值

经过上面两步后,native项目就成功导入了flutter模块,这时候就可以来运行native项目。但在运行native项目时却又可能出现如下错误。

该问题该怎么解决尼?其实在上图的最下面已经给出解决方案了,就是native项目必须使用Java 8,否则不让运行。所以我们需要在app目录下的build.gradle文件中添加如下代码。

javascript 复制代码
    android {
        compileOptions {
            sourceCompatibility 1.8
            targetCompatibility 1.8
        }
    }

然后继续运行native项目,这时候就能够在设备上跑起来了,但如何验证flutter模块是否打包进apk里尼?这时候就可以借助Android Studio的apk分析工具。通过该工具可以发现apk包由以下内容组成。

其中flutter_assets存放的就是flutter代码,到这里native项目就成功的导入了flutter模块。

注意:如在果项目中使用AndroidX,就会导致很严重的兼容性问题。所以如果项目中使用了AndroidX,则要慎重导入flutter模块。如果一定要导入,则可以去阅读flutter官方提供的解决方案------AndroidX compatibility

2、native项目加载flutter页面

经过前面的一些操作,我们就在Native项目中成功依赖了flutter模块,那么下面学习如何在Native项目中加载flutter页面。通过查看flutter模块代码可以发现,该模块提供了以下两种方式来加载flutter页面。

  1. 将flutter页面构建成View,通过addView来显示flutter页面
  2. 将flutter页面构建成Fragment,通过对fragment的操作来显示flutter页面

2.1、将flutter页面构建成View

在flutter模块的Flutter类中给我们提供了一个方法------createView。通过该方法,我们可以将flutter页面构建成一个View。而View的相关操作想必对于Android开发者来说都不陌生,所以就通过addView将flutter页面添加到相应的地方。实现代码如下:

javascript 复制代码
    public void onLoadFlutter(View view) {
        View flutterView = Flutter.createView(this, getLifecycle(), "route1");
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(600, 600);
        layoutParams.topMargin = 100;
        addContentView(flutterView, layoutParams);
    }

2.2、将flutter页面构建成fragment

同样,flutter模块也提供了方法------createFragment,通过该方法就将flutter页面构建成一个fragment,然后根据fragment的操作将flutter页面添加到相应的地方。实现代码如下:

javascript 复制代码
    public void onLoadFlutter(View view) {
       FragmentTransaction transaction= getSupportFragmentManager().beginTransaction();
       transaction.replace(R.id.someContainer,Flutter.createFragment("这里是flutter页面"));
       transaction.commit();
    }

2.3、flutter页面

在前面讲述了如何在native项目中加载flutter页面,下面就来看一下flutter页面的代码。代码还使很简单的,基本的都是创建module时自动生成的代码。

javascript 复制代码
import 'package:flutter/material.dart';
import 'dart:ui';

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

class MyApp extends StatelessWidget {
  final String initParams;

  MyApp({Key key, @required 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 {
  final String initParams;

  MyHomePage({Key key, this.title, this.initParams}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final String initParams;

  _MyHomePageState(this.initParams);

  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:$initParams',
              style: TextStyle(color: Colors.red),
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

可以发现,在上面代码中,我们传入了一个初始化属性,它其实就是一个路由名称,但其实我们也传入一个json或者其他类型的数据,从而来做一些其他操作。其实这样就可以看做native与flutter之间的一种通信。

3、flutter模块的调试

3.1、flutter模块的热重载

flutter的优势之一就是在开发过程中能够通过热重载功能来实现快速的调试,但通过运行上面代码就会发现,flutter模块代码修改后无法立即生效,需要重新打包Native才能生效。这样就让flutter的一个重大优势失效了,降低了调试效率。那么我们能不能在混合项目中做到flutter模块的热重载尼?其实也是可以的,但需要经过一些步骤。

1. 首先,关闭当前应用,注意:是要杀死当前应用所在进程,而不是退出应用

2. 其次,在flutter模块中输入命令flutter attach,就会显示以下内容。

3. 最后,再次打开应用,就会出现如下内容。

请注意图中的这段话

? To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".

它告诉我们如果要热重载就按r 键,想要热重启就按R 键。当修改flutter代码后,按下r键,就会出现以下提示,代表修改成功。

经过上面的一些步骤,我们就可以在混合项目中使用flutter的热重载功能,做到flutter修改后的立即生效。

3.2、flutter模块的调试

其实混合项目的flutter模块调试与flutter项目的的唯一却别就是如何在Android Studio与设备之间建立socket连接。在flutter项目中,我们可以直接点击debug按钮来进行调试,但在混合项目中,该按钮就不起作用了,得通过其他方式来建立连接。Android Studio给我们提供了flutter attach按钮,通过该按钮,flutter模块就能跟设备建立连接,就能对flutter模块进行调试。

4、总结

通过上面的一些讲解,相信就能够使用native+flutter的混合开发了。但细心一点就会发现,在前面的讲解中,flutter模块并没有与native项目进行通信,那么该如何通信尼?在笔者的下一篇文章会进行详细讲解。

最后

如果你看到了这里,觉得文章写得不错就给个赞呗?

更多Android进阶指南 可以详细Vx关注公众号:Android老皮 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

相关推荐
京东云开发者17 分钟前
Joycode 无法跨项目读取源码怎么办?MCP Easy Code Reader 帮你解决!
程序员
京东云开发者24 分钟前
宝剑锋从磨砺出——零售数据库内核,为大促铸剑!
程序员
一颗苹果OMG1 小时前
随着AI的发展,测试跟prompt会不会成为每个程序员的必修课
前端·程序员·全栈
文心快码BaiduComate4 小时前
Comate Figma2Code智能体升级,畅享Figma2Code不受限
人工智能·程序员·前端框架
知了一笑7 小时前
开发者做产品,摆正技术的位置
程序员
努力的小郑16 小时前
今晚Cloudflare一哆嗦,我的加班计划全泡汤
前端·后端·程序员
摆烂工程师19 小时前
今天 Cloudflare 全球事故,连 GPT 和你的网站都一起“掉线”了
前端·后端·程序员
晴殇i1 天前
这个前端工具杀疯了!发布一周狂揽 10k Star,Snapchat 开源框架重新定义跨平台
前端·程序员
大模型教程1 天前
RAG技术详解:让大语言模型减少幻觉
程序员·llm·agent