Android原生嵌入Flutter模块

读这篇文章的前提是,你对Flutter已经有一定了解,或者已经达到会开发Flutter的程度,并且Flutter相关环境已经配置OK!

本文所展示项目的运行环境:

FlutterSDK版本:flutter_windows_2.10.1-stable
AndroidStudio版本:Bumblebee | 2021.1
AndroidSDK版本:31
Gradle版本:7.2

第一步:在你的安卓原生项目父级目录下),执行命令:

flutter create -t module --org com.example my_flutter

此时会创建出一个包名为com.example,项目名为my_flutter的flutter项目:

注意,flutter项目跟原有项目是同级目录
在这里插入图片描述
. 开头的文件或文件夹里的内容,都尽量不要修改,!

第二步:打开原生项目的setting.gradle,在include ':app’下方添加如下代码:

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

第三步:打开原生项目app下的build.gradle,添加如下代码:

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

步骤很简单,但当编译时会出现各种问题,如果你遇到一下几种问题,可以找到对应解决办法:

1.如果遇到Android SDK Command-line Tools相关问题,可以在SDK管理器中安装:
在这里插入图片描述
2.如果遇到android-licenses相关问题,可以执行命令:

flutter doctor --android-licenses

提示Y/N时,一路选择Y即可!

3.如果遇到:Failed to apply plugin class ‘FlutterPlugin’:

打开setting.gradle,将repositoriesMode改为:RepositoriesMode.PREFER_PROJECT

4.如果遇到引用的第三方库解析失败:

打开setting.gradle,添加maven:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
    repositories {
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/repository/central' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
        google()
        mavenCentral()
    }
}

打开原生跟目录下的build.gradle,添加maven:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/repository/central' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.1.1'
    }
}

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/repository/central' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

编译通过后,项目会变成这样:
在这里插入图片描述
爆红处可以不用理会,只要运行成功即可!

小提示:

flutter clean命令,可清除生成的.android、.ios、.packages、.dart_tool文件夹;
flutter packages get命令,可重新生成以上文件;
在项目因某些原因运行出错但又找不到其他原因时,可尝试使用上述步骤解决!

打开my_flutter的lib,就可以开发flutter项目页面了!

从原生跳往Flutter页面有多种途径,首先,需要在原生项目的清单文件中声明FlutterActivity:

<activity
    android:name="io.flutter.embedding.android.FlutterActivity"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize" />

在原生页面中,通过startActivity执行跳转:

startActivity(
      FlutterActivity.createDefaultIntent(context)
    );

这是最简单最直接的跳转方式,执行后会直接通过Flutter项目的main入口进入Flutter页面,但其有一个大问题是,进入Flutter页面,就需要先加载Flutter引擎,这就导致跳转过程非常慢,会明显感觉到卡顿,这里依照官方提供的解决方案,我们可以在Application 中预先加载一个引擎缓存起来:

public class MyApplication extends Application {
  
  @Override
  public void onCreate() {
    super.onCreate();
    FlutterEngine flutterEngine = new FlutterEngine(this);
    flutterEngine.getDartExecutor().executeDartEntrypoint(
      DartEntrypoint.createDefault()
    );
    FlutterEngineCache
      .getInstance()
      .put("my_engine_id", flutterEngine);
  }
}

然后跳转时使用已缓存的引擎:

 startActivity(
      FlutterActivity
        .withCachedEngine("my_engine_id")
        .build(currentActivity)
      );

此时,跳转将会变的非常流畅,跟原生跳转无差别!

以上步骤其实已经实现了原生+flutter混合开发的初步逻辑了,但我们知道,实际情况下,我们可能会使用Flutter做多个不同的模块,那不同模块的首页必然也不相同,以上方法则默认通过flutter的main函数进入一个默认的flutter主页,无法满足需求!那该怎么办呢,别急,官方提供了通过路由跳转的方法:

startActivity(
      FlutterActivity
        .withNewEngine()
        .initialRoute("test")
        .build(currentActivity)
      );

此时我们可以在flutter的main.dart中修改main方法如下:

//通过路由启动页面
void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
  switch (route) {
    case 'test1':
      return const Test1();
    case 'test2':
      return const Test2();
    case 'test3':
      return const Test3();
    default:
      return const Test1();
  }
}

Test1…是我创建的不同Flutter页面!

此时,你就可以通过initialRoute方法传入不同的路由,跳转到不同的页面!

 //使用新Flutter引擎
 binding.btnRoute.setOnClickListener(view -> {
       String[] routes = new String[]{"test1", "test2", "test3"};
       new AlertDialog.Builder(this)
               .setItems(routes, (dialogInterface, i) -> {
                   startActivity(FlutterActivity
                           .withNewEngine()
                           .initialRoute(routes[i])
                           .build(MainActivity.this));
               })
               .create()
               .show();
   });

效果如下:
在这里插入图片描述
我们发现,跳转过程明显卡顿,这是应为跳转时使用了新的引擎withNewEngine(),那我们是否可以使用已缓存的引擎,去通过路由跳转呢?可以,但不能像使用withNewEngine一样使用withCachedEngine跳转路由,因为withCachedEngine没有initialRoute方法!(关于为什么已缓存的引擎无法在设置初始路由的原因,可以参考官方文档)

Flutter给了我们解决方案,就是在创建引擎时设置初始路由:

flutterEngine = new FlutterEngine(this);
flutterEngine.getNavigationChannel().setInitialRoute("your/route/here");
flutterEngine.getDartExecutor().executeDartEntrypoint(
  DartEntrypoint.createDefault()
);
FlutterEngineCache
  .getInstance()
  .put("my_engine_id", flutterEngine);
}

然后我们就可以像上面通过window.defaultRouteName接收路由的方式一样,跳转对应的flutter页面!

当然,我们还有另外一种思路,即我可以根据Flutter的功能模块,创建多个对应的FlutterEngine,每个FlutterEngine设置不同的入口函数进入不同的Flutter界面:

FlutterEngine flutterEngine1 = new FlutterEngine(this);
String pathToBundle = FlutterInjector.instance().flutterLoader().findAppBundlePath();
flutterEngine1.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(pathToBundle, "test1"));
FlutterEngineCache.getInstance().put("test1_engine", flutterEngine1);

FlutterEngine flutterEngine2 = new FlutterEngine(this);
flutterEngine2.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(pathToBundle, "test2"));
FlutterEngineCache.getInstance().put("test2_engine", flutterEngine2);

FlutterEngine flutterEngine3 = new FlutterEngine(this);
flutterEngine3.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(pathToBundle, "test3"));
FlutterEngineCache.getInstance().put("test3_engine", flutterEngine3);

Flutter的main.dart中:

//通过设置不同启动入口启动页面
void test1() => runApp(const Test1());

void test2() => runApp(const Test2());

void test3() => runApp(const Test3());

通过withCachedEngine执行跳转:

//使用已缓存的Flutter引擎
binding.btn1.setOnClickListener(view -> {
    startActivity(FlutterActivity
            .withCachedEngine("test1_engine")
            .build(MainActivity.this));
});

binding.btn2.setOnClickListener(view -> {
    startActivity(FlutterActivity
            .withCachedEngine("test2_engine")
            .build(MainActivity.this));
});

binding.btn3.setOnClickListener(view -> {
    startActivity(FlutterActivity
            .withCachedEngine("test3_engine")
            .build(MainActivity.this));
});

效果如下:
在这里插入图片描述
如图,还是非常流畅的!

当然,还有其他方式如FlutterFragment,FlutterView等,具体可以参考官方文档:

https://flutter.cn/docs/development/add-to-app/android/project-setup

打包release注意事项:

在实际打包release过程中发现了若干问题:

  • Flutter 当前仅支持 为 x86_64,armeabi-v7a 和 arm64-v8a 构建预编(AOT)的库;
  • 如果集成的有umeng多渠道,会导致打包后安装直接闪退;
  • 使用上面介绍的最后一种多引擎不同入口方式,会导致启动flutter界面黑屏;

第一个问题就不说了;
第二个问题目前只能删除AndroidManifest中的umeng的meta-data,同时删除build.gradle中多渠道配置的代码,然后在初始化UMConfigure时手动修改渠道名(稍显麻烦但没办法);
第三个问题,debug模式下没问题,但release就不行,目前不清楚原因,所以可以使用在创建引擎缓存时设置初始路由;

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Flutter是一种跨平台的移动应用开发框架,可以同时在iOS和Android上运行。Flutter使用Dart语言编写,具有热重载功能,可以快速开发高性能、美观的应用程序。Flutter的UI是自己绘制的,不依赖于操作系统的原生控件,因此可以实现高度自定义的UI效果。 Android原生开发是指使用Java或Kotlin编写Android应用程序,使用Android SDK提供的原生控件和API。原生应用程序可以充分利用Android操作系统的功能和性能,但需要针对不同的设备和版本进行适配。 总的来说,FlutterAndroid原生开发的区别在于开发语言、UI实现方式和跨平台能力。Flutter使用Dart语言,UI自绘,可以跨平台运行;而Android原生开发使用Java或Kotlin语言,依赖于操作系统的原生控件和API,只能在Android上运行。 ### 回答2: Flutter是一个开源的移动应用开发框架,而Android原生是指使用Java或Kotlin等本地语言编写的应用程序。下面是FlutterAndroid原生之间的主要区别: 1. 学习曲线:Flutter使用Dart语言开发,如果你已经熟悉了JavaScript或Java等其他语言,学习Flutter也许会花费你一些时间。但是Flutter的开发文档与工具是易于理解和使用的,所以Flutter的学习曲线相对于Android原生会更加平缓。 2. 性能:Flutter使用自己的渲染引擎来绘制用户界面,其称为“Skia”。与Android原生相比,Flutter在UI性能上可能会有一些优势。Flutter采用了一些复杂的技术来在运行时优化代码,并且可以使用Google的Dart编译器来生成高效的原生代码。 3. 开发效率:Flutter的开发速度相对于Android原生也许更快。由于Flutter的热重载功能,您可以更快地查看您所做的更改,并在不刷新应用程序的情况下保存这些更改。此外,Flutter具有很好的跨平台开发支持,您可以在同一代码库中以相同的方式开发iOS和Android应用。 4. 生态系统:Flutter生态系统中的插件和库数量与Android原生相比仍然不足。但是,越来越多的开发人员和组织机构开发了各种各样的插件和库来帮助Flutter开发人员快速开发应用。 5. 设计自由度:Flutter相对于Android原生提供了更多灵活的设计自由度。Flutter应用程序可以组合使用各种小部件和布局,以创建非常独特的用户界面和动画效果。 综上所述,FlutterAndroid原生的区别在于性能、学习曲线、开发效率、生态系统和设计自由度等方面。选择一种适合自己的框架取决于您的具体需求和项目要求,需要根据实际情况进行权衡。 ### 回答3: Flutter(也称为Flutter UI框架)是一个跨平台的移动应用程序开发框架,由谷歌(Google)开发。 它允许开发人员以一种统一的语言(Dart)构建高性能,高保真度的移动应用程序,可在Android和iOS等平台上运行。Flutter基于自己的渲染引擎和框架建立,其中包括许多构建UI的内置组件。Flutter具有以下区别和优势: 1.基于Dart语言:与Java和Kotlin不同,Dart是一种强类型静态语言,也支持动态语言特性。Flutter的完整生态系统都是Dart编写,因此开发人员可以在编写Flutter代码时使用所有Dart的语言特性。 2.完全自定义UI:Flutter的Widget框架提供了大量的预置组件,可以自定义和扩展,使得开发人员可以自由地构建独特的,自定义的UI。 3.高性能:Flutter 框架可以通过达到每秒60帧(FPS)的性能来实现对动画和过渡的支持,这是传统的基于WebView的Hybrid移动应用程序难以匹敌的。 4.快速迭代和快速开发:由于Flutter使用Hot reloading可以快速加载并重新加载UI,因此可以大大减少调试时间和部署时间。 5.跨平台开发:Flutter 允许开发人员在所有平台上构建相同的应用程序,包括Android和iOS,从而实现在延长开发周期的同时实现保证强一致性的开发。 与Flutter相比,Android原生的开发主要集中在Java和Kotlin之上,以使用Android SDK为框架,以构建在Android原生应用程序。而Android原生的应用程序开发具有以下优势和限制: 1.更快的性能:Android原生应用程序始终是高性能的,因为它们直接在设备上运行而不需要中间层。 2.外观和风格与设备一致:为了确保Android应用程序看起来和操作体验与设备相同,Android原生开发支持通过设置特定的样式,颜色和控件来实现此目的。 3.专业开发支持:Android原生应用程序开发具有良好的集成开发环境,具有权限系统,可提供良好的面向开发人员的支持。 4.固定生态系统:Android原生应用程序必须在特定版本的Android API上运行,这意味着必须使用不同的软件包,类和框架,这可能会引起问题。 总之,FlutterAndroid原生应用程序开发是为相同平台开发应用程序的两种不同方法。Flutter提供了快速迭代和跨平台开发的优势,而Android原生应用程序则提供了更快的性能可靠性和与设备外观和风格的一致性优势。根据不同的需求,开发人员可以选择使用适合他们需求的一种或同时使用这两种方式来开发移动应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白玉梁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值