現有Android項目集成Flutter

一、前言

Flutter現在已經很火了,但是如果我們要想使用Flutter開發,在新的Flutter項目上集成以前的所有代碼肯定是不現實的,同時又不想將Flutter直接侵入到我們的項目結構中去,於是最優解就是將開發的Flutter項目單獨編譯成aar,然後以組件的形式被主工程依賴。

這樣做的好處是顯而易見的:對Flutter進行探索開發的同學可以在自己的Flutter工程內編寫dart代碼,獨立運行調試,完成的時候打包成aar集成到主工程中供寫native代碼的同學接入,兩方協同工作,不會產生衝突。

二、打包apk並分析

首先創建flutter工程,會得到如下目錄

在這裏插入圖片描述

在命令行輸入打包命令 flutter build apk

會編譯生成apk文件 位於 build/app/outputs/apk/release/app-release.apk

打開apk可以看到,裏面目錄爲

在這裏插入圖片描述

可以看到多出來很多東西,這些產物都來自於flutter的構建代碼,

android/app/build.gradle中依賴了了flutter.gradle

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

通過閱讀flutter.gradle的構建源碼,可以發現在構建apk的過程中,會將需要的文件構建到apk中。

1、assets文件夾

assets文件夾下面有flutter_assets文件夾、flutter_shared文件夾、isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr文件

  • flutter_assets裏是flutter工程產生的assets文件
  • flutter_shared裏是封裝在flutter.jar裏面的處理字符編碼的ICU庫
  • isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr爲特定平臺的數據和指令

2、lib文件夾

lib文件夾下是特定平臺(arm或者x86)的so文件,flutter在Android平臺下會默認生成arm-v7架構的的so庫。

三、打包aar

上面通過編譯命令得到了apk,如果要想打包aar,理論上只需要把app/build.gradle中的apply plugin: 'com.android.application改爲apply plugin: 'com.android.library,同時註釋掉applicationId "com.flutterappfirst",並且將清單文件修改爲:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.flutterappfirst"/>

然後執行以下命令,就能得到app-release.aar文件

#!/bin/bash

flutter clean
cd android
./gradlew assembleRelease

但是,我們將aar解壓然後看其目錄結構,如下圖:

在這裏插入圖片描述

我們發現在aar文件夾下的assets裏面缺少了flutter_shared文件夾,icudtl.dat文件正是在該文件夾裏面,也就是說flutter.gradle在編譯流程中並沒有將icudtl.dat文件打進aar包裏面,那麼我們的解決辦法是將該文件夾手動拷貝到flutter工程中,如下圖

在這裏插入圖片描述

然後再次執行上述打包aar的命令,得到app-release.aar文件,正確的結構如下圖:

在這裏插入圖片描述

可以看到flutter_shared文件夾已經放到assets目錄裏面了。

四、集成到現有Android項目

上述打包成功的aar就可以作爲普通的aar集成到Android項目中了

1、拷貝aar到現有android項目中,拷貝到libs目錄下

2、配置build.gradle

repositories {
    flatDir { dirs 'libs' }
}

dependencies {
	compile(name: 'app-release', ext: 'aar')
}

當然也可以將aar發佈到jcenter之類的遠程倉庫中,這個流程就跟之前發佈aar流程一樣了,然後在build.gradle中進行遠程導入就OK

3、拷貝Flutter提供的集成類到項目中

因爲集成aar後需要將Flutter寫的界面在Android項目中進行展示,那麼就需要有個橋去調用,那麼具體的橋Flutter sdk已經提供了代碼,具體目錄爲${flutter_sdk}/packages/flutter_tools/templates/module/android/library/Flutter.tmpl/src/main/java/io/flutter/facade,將facade包直接拷到你現在的Android項目中,或者打包成jar再拷貝集成到現有項目中。

我這邊已經打好jar包,可以直接下載,然後導入到工程中
flutter-facade.jar

4、展示Flutter界面

在某個新建的activity中調用如下代碼:

/**
 * @author xueshanshan
 * @date 2018/12/28
 */
public class FlutterMainActivity extends BaseActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FlutterView flutterView = Flutter.createView(this, getLifecycle(), "");
        setContentView(flutterView);
    }
}

然後就能展示Flutter void main() => runApp(new MyApp());這句話對應的界面了。
但是,一般情況下我們是根據原生工程調用讓Flutter生成不同的組件作爲View來供原生工程調用,那麼我們就可以從這個main函數入手

void main() => runApp(_widgetForRoute(window.defaultRouteName));
Widget _widgetForRoute(String route) {
  switch (route) {
    case 'route1':
      return SomeWidget(...);
    case 'route2':
      return SomeOtherWidget(...);
    default:
      return Center(
        child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
      );
  }
}

這樣,我們就可以在不同的界面加載不同的flutter組件了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章