In order to actively embrace new technology and optimize RN’s performance issues, it was decided to introduce the Flutter technology stack into new business requirements

The development of the Flutter mixing stack can be divided into two modes

Native engineering is directly dependent on development

Add the following code to setting.gradle:

setBinding(new Binding([gradle: this])) evaluate(new File( settingsDir, '.. /.. / flyflutter Module project root /.android/ include_flyflutter. Groovy ')Copy the code

Next, add the following code in App build.gradle:

 implementation project(':flutter')
Copy the code

Finally, add the following code to build. Gradle of the main project:

repositories {
buildscript {
        maven {
            url 'http://download.flutter.io'
        }
    }
}
    
allprojects {
    repositories {
        maven {
            url 'http://download.flutter.io'
        }
    }
}

Copy the code

Native projects are connected to aar

New Flutter Module project

flutter create -t module xx_module
Copy the code

The directory structure is as follows

// Modlue -. Android // Android test project -. Ios // ios test Project - lib // Main project - main.dart // Pubspec Flutter tripartite package configuration fileCopy the code

Flutter in provides the packaged module into the aar command, the generated aar file path for xx_modlue/build/host/outputs/repo

flutter build aar
Copy the code

You can complete the aar reference by importing the generated AAR file into the Android development project

Up to now, the introduction of aar is basically normal, but there is a problem, that is, every development needs to manually copy the generated AAR package to the main project for dependency, which is not only troublesome to operate but also causes errors. Therefore, it is the best practice to make the packaging and introduction process of Flutter into the common mode of daily development

Analysis of packing and uploading process of FLUTTER:

The AAR file generated by the Flutter needs to be uploaded to Maven in accordance with the daily development process, so the first task is to solve the aar uploading problem

View the generated aar pom file directory below will find the main engineering rely on third-party aar packages can be downloaded to xx_modlue/build/host/outputs/repo path, pom file is as follows:

The < project xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" > < modelVersion > 4.0.0 < / modelVersion > < groupId > com. XXX. Flutter < / groupId > < artifactId > XXX < / artifactId > <version>release 0.0.7</version> <packaging>aar</packaging> <dependencies> <groupId> IO. The < artifactId > flutter_embedding_release < / artifactId > < version > 1.0.0 - af51afceb8886cc11e25047523c4e0c7e1f5d408 < / version > <scope>compile</scope> </dependency> <dependency> <groupId>io.flutter</groupId> The < artifactId > armeabi_v7a_release < / artifactId > < version > 1.0.0 - af51afceb8886cc11e25047523c4e0c7e1f5d408 < / version > <scope>compile</scope> </dependency> <dependency> <groupId>io.flutter</groupId> The < artifactId > arm64_v8a_release < / artifactId > < version > 1.0.0 - af51afceb8886cc11e25047523c4e0c7e1f5d408 < / version > <scope>compile</scope> </dependency> <dependency> <groupId>io.flutter</groupId> <artifactId>x86_64_release</artifactId> < version > 1.0.0 - af51afceb8886cc11e25047523c4e0c7e1f5d408 < / version > the < scope > compile < / scope > < / dependency > < / dependencies > </project>Copy the code

After analyzing the POM file, we can see that when uploading the AAR generated by the main project, we also need to upload the downloaded third-party AAR to maven library. Therefore, we know that the specific engineering script process is as follows:

Obtain the aar path that is generated. 2. Upload the AAR file that the third party depends on

The script is as follows:

deploy_aar(){ mvn deploy:deploy-file \ -DpomFile="$FILE_PATH/$NAME.pom" \ -DgeneratePom=false \ -Dfile="$FILE_PATH/$NAME.aar" \ -Durl="http://xxx.xxx.xxx:xxx/repository/public/" \ -DrepositoryId="nexus" \ -dpackaging =aar \ -s="mvn-settings. XML "\ -dversion ="$VERSION"} projectDir=" PWD Flutter pub get # delete folders rm - rf ` PWD ` / build/host/outputs/repo / # modified version number group = "com. XXX. Flutter" type = "release" #type="debug" #type="profile" version="${type}-0.0.7" artifactId=" XXX "echo Path = ` PWD ` / android/Flutter/build gradle sed -i ' ' '29 s / ^. * $/ group "' ${group} "/ '${path} echo" replace Flutter/build. Gradle The version is ${version} "in the path = ` PWD ` / android/Flutter/build gradle sed -i ' '30 s / ^. * $/ version"' ${version} "/ '${path} # Path = 'PWD' # shellcheck disable= 'SC2006 p=' find ${path}/build/host/outputs/repo -type f -name "*${type}*.aar"` echo "${p}" array=(${p//'\n'/}) currentName="" currentPath="" currentPom="" currentDir="" # shellcheck disable=SC2068 for item in ${array[@]} do resFile=`basename ${item}` echo "${item}" result=$(echo ${resFile} | grep "flutter_release") if [[ "$result" == "" ]] then lenght=${#item}  sub=${item:0:${lenght}-3} pom="${sub}pom" resFileLenght=${#resFile} subDir=${item:0:${lenght}-${resFileLenght}} curName=`echo ${resFile} | cut -d "-" -f 2` curNameLenght=${#curName} subVersion=${curName:0:${curNameLenght}-4} nameLenght="${#resFile}" subName=${resFile:0:${nameLenght}-4} export FILE_PATH="${subDir}" export NAME="${subName}" export VERSION=${subVersion} deploy_aar else nameLenght="${#resFile}" subName=${resFile:0:${nameLenght}-4} currentName="${subName}" currentPath=${item} currentPath=${item} lenght=${#item} sub=${item:0:${lenght}-3} currentPom="${sub}pom" resFileLenght=${#resFile} subDir=${item:0:${lenght}-${resFileLenght}} currentDir=${subDir} fi done cd "${currentDir}" echo `pwd` mv "${currentName}.aar" "${artifactId}-${version}.aar" mv "${currentName}.pom" "${artifactId}-${version}.pom" cd ${projectDir} echo `pwd` currentName="${artifactId}-${version}" currentPath="${currentDir}${currentName}.aar" currentPom="${currentDir}${currentName}.pom" echo "current name is ${currentName}" echo "current path is ${currentPath}" echo "currentPom is ${currentPom}" echo ${artifactId}" sed -i "" 6s/^.*$/ <artifactId>'${artifactId}'<\/artifactId> /' ${currentPom} echo "currentDir is ${currentDir}" echo "currentVersion is ${version}" export FILE_PATH="${currentDir}" export NAME="${currentName}" export VERSION=${version} deploy_aarCopy the code

After uploading Maven successfully, the main project relies on the Flutter code in accordance with the process of adding the third-party SDK.

Selection of contrast

The name of the advantages disadvantages
Native engineering is directly dependent on development Access to fast The engineering structure was complex and the Flutter development could not be separated from the Native development process
Native projects are connected to aar The DEVELOPMENT of Flutter is decoupled from the native development process The initial access process is complicated

Finally, maven is selected to connect to the AAR for further expansion

Flutter mixing stack selection

After completing the Flutter hybrid development access process, there are mixed stack management issues, and the main problem solved in the mixed solution is how to handle the alternate Flutter and Native pages. Integrated with the current open source framework, the selection is FlutterBoost

FlutterBoost Flutter terminal access:

FlutterBoost.singleton.registerPageBuilders(<String, PageBuilder>{
      testhome: (String pageName, Map<dynamic, dynamic> params, String _) =>
          MyHomePage(title: ''),
      shoppingcar: (String pageName, Map<dynamic, dynamic> params, String _) {
        String platformItemNo = '';
        if (params.containsKey("platformItemNo")) {
          platformItemNo = params['platformItemNo'];
          NativeChat.print(platformItemNo);
        }
        return ShoppingCar(platformItemNo: platformItemNo);
      },
      login: (String pageName, Map<dynamic, dynamic> params, String _) =>
          LoginPage(),
      overlay: (String pageName, Map<dynamic, dynamic> params, String _) =>
          OverlayPage(),
    });
Copy the code

Android terminal access:

Application initialization code:

val router = INativeRouter { context, url, urlParams, requestCode, exts -> PageRouter.openPageByUrl(context, url, urlParams) } val boostLifecycleListener = object : FlutterBoost.BoostLifecycleListener { override fun onEngineCreated() { } override fun onPluginsRegistered() { } override  fun beforeCreateEngine() { } override fun onEngineDestroy() { } } val platform = FlutterBoost.ConfigBuilder(application, router) .isDebug(BuildConfig.DEBUG) .whenEngineStart(FlutterBoost.ConfigBuilder.ANY_ACTIVITY_CREATED) .renderMode(FlutterView.RenderMode.texture) .lifecycleListener(boostLifecycleListener) .build() FlutterBoost.instance().init(platform)Copy the code

Route configuration code

Object PageRouter {/** * route map */ val pageName: HashMap<String? , String? > = object : HashMap<String? , String? >() { init { put("xxxx://shoppingCar", "shoppingCar") put("xxxx://login", "login") put("xxxx://home", "home") put("xxxx://overlay", "overlay") } } const val SHOPPING_CAR = "xxxx://shoppingCar" const val LOGIN_PAGE = "xxxx://login" const val OVERLAY = "xxxx://overlay" const val BUYER_PRODUCT_DETAIL = "xxxx://buyer/productdetail" const val TEST_SECOND = "xxxx://testSecond" @JvmOverloads fun openPageByUrl( context: Context, url: String, params: Map<*, *>? , requestCode: Int = 0 ): Boolean { val path = url.split("\\?" ).toTypedArray()[0] Log.i("openPageByUrl", path) return try { when { pageName.containsKey(path) -> { val intent = BoostFlutterActivity.withNewEngine().url(pageName[path]!!) .params(params!!) .backgroundMode(BoostFlutterActivity.BackgroundMode.opaque) .build(context) if (context is Activity) { context.startActivityForResult(intent, requestCode) } else { context.startActivity(intent) } return true } url.startsWith(TEST_SECOND) -> { context.startActivity( Intent( context, SecondActivity::class.java ) ) return true } else -> false } } catch (t: Throwable) { false } } }Copy the code

Native jump logic

Flutterboost.instance ().channel().addMethodCallHandler {call, Result -> when (call.method) {"baseUrl" -> {result.success(ApiConstant.getapiURL ())}}} val params = hashMapOf<String, String>() params["param"] = param PageRouter.openPageByUrl(this, PageRouter.SHOPPING_CAR, params)Copy the code

The Flutter test environment is built

Testing is probably the most ridiculed in mixed development projects. Debugging packaged with Native takes time and effort and requires a high understanding of the basic process of native for front-end development