当前位置:   article > 正文

Android项目中集成Flutter,实现秒开Flutter模块

Android项目中集成Flutter,实现秒开Flutter模块

本文目标

成功在Android原生项目中集成Flutter

Warning

  • 从Flutter v1.1.7版本开始,Flutter module仅支持AndroidX应用
  • 在release模式下Flutter仅支持以下架构:x86_64,armeabi-v7a,arm64-v8a,不支持mips和x86,所以引入Flutter前需要选取Flutter支持的架构

 

  1. android{
  2. //...
  3. defaultConfig {
  4. //配置支持的动态库类型
  5. ndk {
  6. abiFilters 'x86_64','armeabi-v7a', 'arm64-v8a'
  7. }
  8. }
  9. }

混合开发的一些适用场景

  • 在原有项目中加入Flutter页面

 

  • 原生页面中嵌入Flutter模块

 

  • 在Flutter项目中嵌入原生模块

 

主要步骤

  • 创建Flutter module
  • 为已存在的Android项目添加Flutter module依赖
  • 早Kotlin/Java中调用Flutter module
  • 编写Dart代码
  • 运行项目
  • 热重启/重新加载
  • 调试Dart代码
  • 发布应用

请把所有的项目都放在同一个文件夹内

 

  1. - WorkProject
  2. - AndroidProject
  3. - iOSProject
  4. - flutrter_module

WorkProject下面分别是原生Android模块,原生iOS模块,flutter模块,并且这三个模块是并列结构

创建Flutter module

在做混合开发之前我们需要创建一个Flutter module
这个时候需要

 

  cd xxx/WorkProject /

创建flutter_module

 

flutter create -t module flutter_module

如果要指定包名

 

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

然后就会创建成功

 

  • .android - flutter_module的Android宿主工程
  • .ios - flutter_module的iOS宿主工程
  • lib - flutter_module的Dart部分代码
  • pubspec.yaml - flutter_module的项目依赖配置文件
    因为宿主工程的存在,我们这个flutter_module在布甲额外的配置的情况下是可以独立运行的,通过安装了Flutter和Dart插件的AndroidStudio打开这个flutter_module项目,通过运行按钮可以直接运行

构建flutter aar(非必须)

可以通过如下命令构建aar

 

  1. cd .android/
  2. ./gradlew flutter:assembleRelease

这会在.android/Flutter/build/outputs/aar/中生成一个flutter-release.aar归档文件

为已存在的Android用意添加Flutter module依赖

打开我们的Android项目的 settings.gradle添加如下代码

 

  1. setBinding(new Binding([gradle: this]))
  2. evaluate(new File(
  3. settingsDir.parentFile,
  4. 'flutter_module/.android/include_flutter.groovy'
  5. ))
  6. //可选,主要作用是可以在当前AS的Project下显示flutter_module以方便查看和编写Dart代码
  7. include ':flutter_module'
  8. project(':flutter_module').projectDir = new File('../flutter_module')

setBinding与evaluate允许Flutter模块包括它自己在内的任何Flutter插件,在setting.gradle中以类似:flutter package_info :video_player的方式存在

添加:flutter依赖

 

  1. dependencies {
  2. implementation project(':flutter')
  3. }

添加Java8编译选项

因为Flutter的Android engine使用了Java8的特性,所有在引入Flutter时需要配置你的项目的Java8编译选项

 

  1. //在app的build.gradle文件的android{}节点下添加
  2. android {
  3. compileOptions {
  4. sourceCompatibility = 1.8
  5. targetCompatibility = 1.8
  6. }
  7. }

在Kotlin中调用Flutter module

支持,我们已经为篱笆社区的Android项目添加了Flutter所必须的依赖,接下来我们来看如何在项目中以Kotlin的方式在Fragment中调用Flutter模块,在这里我们能做到让Flutter优化提升加载速度,实现秒开Flutter模块

原生Kotlin端代码

 

  1. /**
  2. * flutter抽象的基类fragment,具体的业务类fragment可以继承
  3. **/
  4. abstract class FlutterFragment(moduleName: String) : IBaseFragment() {
  5. private val flutterEngine: FlutterEngine?
  6. private lateinit var flutterView: FlutterView
  7. init {
  8. flutterEngine =FlutterCacheManager.instance!!.getCachedFlutterEngine(AppGlobals.get(), moduleName)
  9. }
  10. override fun getLayoutId(): Int {
  11. return R.layout.fragment_flutter
  12. }
  13. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  14. super.onViewCreated(view, savedInstanceState)
  15. (mLayoutView as ViewGroup).addView(createFlutterView(activity!!))
  16. }
  17. private fun createFlutterView(context: Context): FlutterView {
  18. val flutterTextureView = FlutterTextureView(activity!!)
  19. flutterView = FlutterView(context, flutterTextureView)
  20. return flutterView
  21. }
  22. /**
  23. * 设置标题
  24. */
  25. fun setTitle(titleStr: String) {
  26. rl_title.visibility = View.VISIBLE
  27. title_line.visibility = View.VISIBLE
  28. title.text = titleStr
  29. title.setOnClickListener {
  30. }
  31. }
  32. /**
  33. * 生命周期告知flutter
  34. */
  35. override fun onStart() {
  36. flutterView.attachToFlutterEngine(flutterEngine!!)
  37. super.onStart()
  38. }
  39. override fun onResume() {
  40. super.onResume()
  41. //for flutter >= v1.17
  42. flutterEngine!!.lifecycleChannel.appIsResumed()
  43. }
  44. override fun onPause() {
  45. super.onPause()
  46. flutterEngine!!.lifecycleChannel.appIsInactive()
  47. }
  48. override fun onStop() {
  49. super.onStop()
  50. flutterEngine!!.lifecycleChannel.appIsPaused()
  51. }
  52. override fun onDetach() {
  53. super.onDetach()
  54. flutterEngine!!.lifecycleChannel.appIsDetached()
  55. }
  56. override fun onDestroy() {
  57. super.onDestroy()
  58. flutterView.detachFromFlutterEngine()
  59. }
  60. }

R.layout.fragment_flutter的布局

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <RelativeLayout
  7. android:id="@+id/rl_title"
  8. android:visibility="gone"
  9. android:layout_width="match_parent"
  10. android:layout_height="@dimen/dp_45"
  11. android:background="@color/color_white"
  12. android:gravity="center_vertical"
  13. android:orientation="horizontal">
  14. <TextView
  15. android:id="@+id/title"
  16. android:layout_width="wrap_content"
  17. android:layout_height="match_parent"
  18. android:layout_centerInParent="true"
  19. android:layout_gravity="center"
  20. android:gravity="center"
  21. android:textColor="@color/color_000"
  22. android:textSize="16sp" />
  23. </RelativeLayout>
  24. <View
  25. android:id="@+id/title_line"
  26. android:visibility="gone"
  27. android:layout_width="match_parent"
  28. android:layout_height="2px"
  29. android:background="@color/color_eee" />
  30. </LinearLayout>

 

  1. /**
  2. * flutter缓存管理,主要是管理多个flutter引擎
  3. **/
  4. class FlutterCacheManager private constructor() {
  5. /**
  6. * 伴生对象,保持单例
  7. */
  8. companion object {
  9. //喜欢页面,默认是flutter启动的主入口
  10. const val MODULE_NAME_FAVORITE = "main"
  11. //推荐页面
  12. const val MODULE_NAME_RECOMMEND = "recommend"
  13. @JvmStatic
  14. @get:Synchronized
  15. var instance: FlutterCacheManager? = null
  16. get() {
  17. if (field == null) {
  18. field = FlutterCacheManager()
  19. }
  20. return field
  21. }
  22. private set
  23. }
  24. /**
  25. * 空闲时候预加载Flutter
  26. */
  27. fun preLoad(context: Context){
  28. //在线程空闲时执行预加载任务
  29. Looper.myQueue().addIdleHandler {
  30. initFlutterEngine(context, MODULE_NAME_FAVORITE)
  31. initFlutterEngine(context, MODULE_NAME_RECOMMEND)
  32. false
  33. }
  34. }
  35. /**
  36. * 初始化Flutter
  37. */
  38. private fun initFlutterEngine(context: Context, moduleName: String): FlutterEngine {
  39. //flutter 引擎
  40. val flutterLoader: FlutterLoader = FlutterInjector.instance().flutterLoader()
  41. val flutterEngine = FlutterEngine(context,flutterLoader, FlutterJNI())
  42. flutterEngine.dartExecutor.executeDartEntrypoint(
  43. DartExecutor.DartEntrypoint(
  44. flutterLoader.findAppBundlePath(),
  45. moduleName
  46. )
  47. )
  48. //存到引擎缓存中
  49. FlutterEngineCache.getInstance().put(moduleName,flutterEngine)
  50. return flutterEngine
  51. }
  52. /**
  53. * 获取缓存的flutterEngine
  54. */
  55. fun getCachedFlutterEngine(context: Context?, moduleName: String):FlutterEngine{
  56. var flutterEngine = FlutterEngineCache.getInstance()[moduleName]
  57. if(flutterEngine==null && context!=null){
  58. flutterEngine=initFlutterEngine(context,moduleName)
  59. }
  60. return flutterEngine!!
  61. }
  62. }

具体业务类使用

 

  1. //在app初始化中初始一下
  2. public class MyApplication extends Application {
  3. @Override
  4. public void onCreate() {
  5. super.onCreate();
  6. FlutterCacheManager.getInstance().preLoad(this);
  7. }
  8. }

收藏页面

 

  1. class FavoriteFragment : FlutterFragment(FlutterCacheManager.MODULE_NAME_FAVORITE) {
  2. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  3. super.onViewCreated(view, savedInstanceState)
  4. setTitle(getString(R.string.title_favorite))
  5. }
  6. }

推荐页面

 

  1. class RecommendFragment : FlutterFragment(FlutterCacheManager.MODULE_NAME_RECOMMEND) {
  2. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  3. super.onViewCreated(view, savedInstanceState)
  4. setTitle(getString(R.string.title_recommend))
  5. }
  6. }

Dart端代码

 

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_module/favorite_page.dart';
  3. import 'package:flutter_module/recommend_page.dart';
  4. //至少要有一个入口,而且这下面的man() 和 recommend()函数名字 要和FlutterCacheManager中定义的对应上
  5. void main() => runApp(MyApp(FavoritePage()));
  6. //必须加注解
  7. @pragma('vm:entry-point')
  8. void recommend() => runApp(MyApp(RecommendPage()));
  9. class MyApp extends StatelessWidget {
  10. final Widget page;
  11. const MyApp(this.page);
  12. @override
  13. Widget build(BuildContext context) {
  14. return MaterialApp(
  15. title: 'Flutter Demo',
  16. theme: ThemeData(
  17. primarySwatch: Colors.blue,
  18. ),
  19. home: Scaffold(
  20. body: page,
  21. ),
  22. );
  23. }
  24. }

Dart侧收藏页面

 

  1. import 'package:flutter/material.dart';
  2. class FavoritePage extends StatefulWidget {
  3. @override
  4. _FavoritePageState createState() => _FavoritePageState();
  5. }
  6. class _FavoritePageState extends State<FavoritePage> {
  7. @override
  8. Widget build(BuildContext context) {
  9. return Container(
  10. child: Text("收藏"),
  11. );
  12. }
  13. }

Dart侧推荐页面

 

  1. import 'package:flutter/material.dart';
  2. class RecommendPage extends StatefulWidget {
  3. @override
  4. _RecommendPageState createState() => _RecommendPageState();
  5. }
  6. class _RecommendPageState extends State<RecommendPage> {
  7. @override
  8. Widget build(BuildContext context) {
  9. return Container(
  10. child: Text("推荐"),
  11. );
  12. }
  13. }

最终效果

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/515335
推荐阅读
相关标签
  

闽ICP备14008679号