专栏首页Android技术分享不得不看的Flutter与Android混合开发

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

记得在flutter刚出来时,笔者就开始学习flutter。但由于当时嫌弃flutter复杂的层级组合且未推出稳定版,所以当时就放弃了深入学习,现如今随着flutter的蓬勃发展及大佬们的力推,就又入坑flutter。

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

1、flutter模块的导入

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

    flutter create -t module flutter_module

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

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

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

```
    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文件中添加如下代码。

    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页面添加到相应的地方。实现代码如下:

    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页面添加到相应的地方。实现代码如下:

    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时自动生成的代码。

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程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在Android中集成Flutter的学习笔记

    Flutter可能是未来跨平台开发的又一技术框架,那么对于一个app,我们不可能完全用flutter来开发,那么就意味着我们需要在已有的Android和iOS代...

    Android技术干货分享
  • 斗鱼直播带你实现:你主播最爱的Android音视频开发

    视频的采集涉及两方面数据的采集:音频采集和图像采集,它们分别对应两种完全不同的输入源和数据格式。

    Android技术干货分享
  • 音视频入门之音频采集、编码、播放

    今天我们学习音频的采集、编码、生成文件、转码等操作,我们生成三种格式的文件格式,pcm、wav、aac 三种格式,并且我们用 AudioStack 来播放音频,...

    Android技术干货分享
  • Flutter单引擎和外接纹理内存优化探索之路

    今年九月初,王者人生Android端及iOS端正式接入flutter跨平台方案来提升开发效率。

    brzhang
  • 现有项目集成flutter排坑指南

    1、如果选择,stable,我们遇到的情况是,IOS上接入之后是跑不了的。切到master上就OK了。

    brzhang
  • Flutter基础篇(7)-- Flutter更新错误全面解决方案(图文+视频讲解)

    (我电脑里面已经安装flutter最新版了。为了演示flutter升级过程,我删除了flutter文件夹,重新去github下载flutter文件,并且执行更新...

    AWeiLoveAndroid
  • 转发 | 闲鱼公开多年 Flutter 实践经验

    flutter-boot核心解决了混合开发模式下的两个问题:flutter混合开发的工程化设计和混合栈。那flutter-boot是如何解决的呢?

    Java帮帮
  • flutter-Mac系统下安装之export PATH=`pwd`/flutter/bin:$PATH

    在执行export PATH=pwd/flutter/bin:$PATH命令的时候踩了一会儿坑,按教程执行完之后,在命令行输入 flutter doctor之后...

    coderZhen
  • Flutter开发:运行项目提示flutter packages get不成功的解决方法

    今天端午节,为了欢度佳节,就算再困也得起床发一篇博文,发完继续睡,顺便祝各路粉丝端午节快乐。

    三掌柜
  • Flutter 更新&升级

    https://flutter-io.cn/posts/announcing-flutter-1-7-9.html

    林小帅

扫码关注云+社区

领取腾讯云代金券