如何利用Fluttify開發一個新的Flutter外掛

小山包發表於2019-12-28

注:目前Fluttify本身並不對外開放,但是內測階段可以免費為你生成外掛,只要提供android端的jar/aar和ios端的framework/.h+.a,或者maven座標和cocoapods名稱即可。

系列文章:

(一)Flutter外掛開發必備 原生SDK->Dart介面生成引擎Fluttify介紹

(二)如何利用Fluttify開發一個新的Flutter外掛

使用Fluttify生成外掛

從原生SDK生成Fluttify產物,本質上也是一個構建的過程,所以Fluttify採用了Gradle外掛的形式。和android構建類似,構建Fluttify也需要提供一個build.gradle,輸入必須的引數後執行gradle fluttify,便能夠生成出一個原生SDK對應的Flutter外掛。 這篇文章會以極光統計SDK作為示例。

快速開始

以JAnalytics SDK的初始化方法為例:

  1. 聯絡我(382146139@qq.com)生成外掛;
  2. ./lib資料夾下新建dart資料夾(這一步是可選的,為了不弄亂資料夾而已);
  3. 建立./dart/janalytics_service.dart檔案(名字隨你喜歡,只是找個地方放初始化程式碼);
  4. 去官網整合指南找初始化程式碼: 4.1 android: JAnalyticsInterface.init(Context context);; 4.2 ios: [JANALYTICSService setupWithConfig:config];;
  5. 編寫Dart程式碼:
import 'package:flutter/cupertino.dart';
import 'package:janalytics_fluttify/src/android/android.export.g.dart'; // 這是生成的程式碼
import 'package:janalytics_fluttify/src/ios/ios.export.g.dart'; // 這是生成的程式碼

class JAnalyticsService {
  static Future<void> init({@required String iosKey}) async {
    // `platform`方法封裝了一些方便多平臺呼叫的邏輯,如果你喜歡也可以直接if else判斷平臺然後各自呼叫各平臺的程式碼
    await platform(
      // pool引數是需要釋放的原生物件的集合,在platform方法執行結束後會自動釋放原生物件,具體可以看本篇下面的說明
      android: (pool) async {
        await cn_jiguang_analytics_android_api_JAnalyticsInterface
            .init(await android_app_Application.get());
      },
      ios: (pool) async {
        final config = await JANALYTICSLaunchConfig.create__();
        await config.set_appKey(iosKey);
        await config.set_channel('developer-default');

        await JANALYTICSService.setupWithConfig(config);
        
        pool.add(config);
      },
    );
  }
}
複製程式碼
  1. 外掛的一個方法編寫完畢。

可以看到在Fluttify的加持下,編寫外掛變成了一件非常輕鬆的事情,想要寫方法的時候就是查官方文件,然後寫對應的dart程式碼,完全遮蔽了原生介面。你不用再一次次的開啟android studioxcode,一次次地在原生和dart之間跳來跳去,再也不用為了在dart和原生之間傳物件寫那一大坨的欄位,跟原生有關的,Fluttify都(盡力)為你提供好dart介面,這就是Fluttify的目標。

接下來大致介紹下生成的外掛的結構以及怎麼呼叫生成的介面。

Fluttify產物工程結構

Fluttify的產物是一個標準的Flutter的外掛工程,所以lib資料夾之上的結構都和普通外掛一樣。lib資料夾下會分成androidios資料夾,分別放置各平臺SDK中的類(列舉/介面等)對應的Dart類(列舉/介面等)。android/ios資料夾下還會各自生成:

  • function.g.dart檔案:生成的所有頂層函式;
  • type_op.g.dart檔案:所有的asis方法,用來判斷型別和造型;
  • ios/android.export.g.dart檔案:匯出所有的ios/android型別;
  • platformview資料夾:生成的所有PlatformView

習慣上會在lib資料夾下再加一個dart資料夾,放置對各平臺進行抽象的程式碼,並且最後對外export的時候,只export這個資料夾下的檔案。

lib資料夾結構概覽:

.
├── janalytics_fluttify.dart
└── src
    ├── android
    │   ├── android.export.g.dart
    │   ├── cn ... android端對應的dart介面
    │   └── type_op.g.dart
    ├── dart
    │   └── janalytics_service.dart
    └── ios
        ├── JANALYTICSBrowseEvent.g.dart
        ├── ...其他生成檔案
        ├── functions.g.dart
        ├── ios.export.g.dart
        └── type_op.g.dart
複製程式碼

基本操作

建立物件

Fluttify中建立物件主要是使用create方法。這個方法在dart端以靜態的非同步方法XX.create__xx的形式提供,其中xx是構造器的引數。形如:

class JANALYTICSLaunchConfig extends NSObject  {
  static Future<JANALYTICSLaunchConfig> create__() async {
    // ...呼叫原生建立物件
  }
}
複製程式碼

如果構造器沒有引數,那麼就直接XX.create__,後面跟兩個下劃線是為了不與SDK中的create方法衝突。

呼叫方法

Fluttify中的所有方法都是非同步的,所以你想要看起來像同步程式碼的話,就要對每個呼叫都加await。其他的就沒什麼好說的,因為Fluttify的目的就是為了讓原生呼叫起來跟dart呼叫起來一模一樣,原生怎麼呼叫,dart這邊就怎麼呼叫。

支援哪些操作

Fluttify會生成SDK中的公開類,公開方法,以及常量。

基礎設施

所有Fluttify生成的工程都會依賴一個基礎設施外掛,也就是foundation_fluttify

這個外掛提供了系統類的dart介面,並且是手寫的。曾經我也嘗試過直接對android.jar和ios的系統framework進行生成,雖然理論上能夠實現,但是效果並不好,生成出來的檔案非常多,光這一個外掛編譯進app的話就要增大好幾Mb,所以放棄了,還是碰到需要的再去手動編寫一下就ok了。

另外foundation_fluttify還提供了一些便利方法,比如platform方法簡化多平臺的呼叫,kNativeObjectPool存放原生物件的dart引用,等等。

原生物件的生命週期

Fluttiy生成的dart程式碼在呼叫過程中產生的原生物件,都會被放入一個叫HEAP的全域性鍵值對型別中,android端為HashMap,ios端為NSDictionary。由於存放在全域性變數中,如果不手動釋放的話,那麼這些物件會一直被強引用,無法釋放。foundation_fluttify中的Ref類(dart)有一個release方法,呼叫它會把對應的原生物件充HEAP中刪除,從而解除強引用。

結語

以上就是使用Fluttify開發一個外掛的介紹。janalytics_fluttify已經上傳到fluttify-project組織下,如果有老鐵對這個外掛感興趣的話可以聯絡我(382146139@qq.com),我可以把你設定為維護者,當然有空閒時間時,我也會進一步開發這個外掛。

如果有想要生成外掛的老鐵也可以聯絡我,目前Fluttify還處於內測階段,不會收取任何費用,有任何反饋都可以往fluttify-feedback提issue,歡迎各位的反饋。

相關文章