Flutter Native混编

Flutter Native混编调研

0. 背景

由于公司现在有多个移动应用已经在线上运行,比如易销售、智慧仓库等等,虽然Flutter拥有一次编写多端使用的优势,但是推倒用Flutter重新实现一遍代价也比较大,最好的折衷方案是在现有App的基础上进行混合开发编译,在拥有了成熟的Flutter技术沉淀以后可以在新应用上快速接入使用,提升开发效率。

1. 混编接入方式

  1. 在宿主项目中增加ndk支持
android {
  //...
  defaultConfig {
    ndk {
      // Filter for architectures supported by Flutter.
      abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
    }
  }
}
  1. 添加Java8支持

    android {
     //...
     compileOptions {
       sourceCompatibility 1.8
       targetCompatibility 1.8
     }
    }
  2. 然后使用Android Studio新建一个Flutter Module项目

img

  1. 在这个Flutter Module项目中进行相关业务开发
  2. 选择以下三种接入方式之一完成混合开发

1. 本地级联编辑

  1. 在宿主项目的setting.gradle中增加本地Flutter Module依赖(假设Flutter Module鱼宿主项目同级)
// Include the host app project.
include ':app'                                    // assumed existing content
setBinding(new Binding([gradle: this]))                                // new
evaluate(new File(                                                     // new
  settingsDir.parentFile,                                              // new
  'my_flutter/.android/include_flutter.groovy'                         // new
))     
  1. 在宿主项目的app中的build.gradle中增加module依赖
dependencies {
  implementation project(':flutter')
}

2. 本地Maven仓库依赖

在Flutter Module中运行

 cd some/path/my_flutter
$ flutter build aar
C:\Users\chao.bai\AndroidStudioProjects\flutter-demos\native-module\flutter_module_pure>flutter build aar
 Building with sound null safety 
Running Gradle task 'assembleAarDebug'...                          12.3s
√ Built build\host\outputs\repo.
Running Gradle task 'assembleAarProfile'...                        29.6s
√ Built build\host\outputs\repo.
Running Gradle task 'assembleAarRelease'...                        30.6s
√ Built build\host\outputs\repo.
Consuming the Module
  1. Open <host>\app\build.gradle
  2. Ensure you have the repositories configured, otherwise add them:
      String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
      repositories {
        maven {
            url 'C:\Users\chao.bai\AndroidStudioProjects\flutter-demos\native-module\flutter_module_pure\build\host\outputs\repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }
  3. Make the host app depend on the Flutter module:
    dependencies {
      debugImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_debug:1.0'
      profileImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_profile:1.0'
      releaseImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_release:1.0'
    }

  4. Add the `profile` build type:

    android {
      buildTypes {
        profile {
          initWith debug
        }
      }
    }

这个命令会生成一个本地仓库(初始位置为有your flutter module/build/host/outputs/repo)

build/host/outputs/repo
└── com
    └── example
        └── my_flutter
            ├── flutter_release
            │   ├── 1.0
            │   │   ├── flutter_release-1.0.aar
            │   │   ├── flutter_release-1.0.aar.md5
            │   │   ├── flutter_release-1.0.aar.sha1
            │   │   ├── flutter_release-1.0.pom
            │   │   ├── flutter_release-1.0.pom.md5
            │   │   └── flutter_release-1.0.pom.sha1
            │   ├── maven-metadata.xml
            │   ├── maven-metadata.xml.md5
            │   └── maven-metadata.xml.sha1
            ├── flutter_profile
            │   ├── ...
            └── flutter_debug
                └── ...

为了依赖生成的AAR,宿主项目必须找到这些文件


      String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
      repositories {
        maven {
            url 'C:\Users\chao.bai\AndroidStudioProjects\flutter-demos\native-module\flutter_module_pure\build\host\outputs\repo'
        }
        maven {
            url "$storageUrl/download.flutter.io"
        }
      }

    dependencies {
      debugImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_debug:1.0'
      profileImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_profile:1.0'
      releaseImplementation 'com.fc.mobile.dms.flutter_module_pure:flutter_release:1.0'
    }

3. 远程Maven仓库依赖

远程仓库依赖可以使用fat-aar三方库将Flutter Module库一起打包生成aar,然后上传至公司maven仓库

2. Native调用Flutter页面

最终我们的目的就是需要在存在的应用上调起Flutter页面,一套代码跨端使用

  1. 对于Android应用,需要在宿主的清单文件中进行注册
<activity
  android:name="io.flutter.embedding.android.FlutterActivity"
  android:theme="@style/LaunchTheme"
  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize"
  />
  1. 在Application中初始化Flutter引擎

       // 实例化
       flutterEngine = new FlutterEngine(this);
    
       // 引擎预热,这么做可以在初次调用Flutter时有更快的相应速度
       flutterEngine.getDartExecutor().executeDartEntrypoint(
         DartEntrypoint.createDefault()
       );
    
       // 根据id缓存对应的引擎
       FlutterEngineCache
         .getInstance()
         .put("my_engine_id", flutterEngine);
  2. 启动页面

    这里使用Activity最为例子,Fragment以及View粒度的实现这里暂不做介绍

myButton.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    startActivity(
      FlutterActivity.createDefaultIntent(currentActivity)
    );
  }
});

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注