MXFlutter上線Flutter pub.dev 三步接入現有工程
相關進展:
更多 MXFlutter 資訊,請關注掘金 MXFlutter Team賬號的相關文章 MXFlutter
MXFlutter 自去年釋出預覽版之後,經過不斷優化和重構 v0.2.1 已在iOS 線上APP使用,同時支援 Android 平臺。由於整個框架的複雜性,業務接入步驟繁多,近期經過一系列的改造和重構,現已重構為標準的 Flutter Package,並在昨天上線官方 pub 庫 mxflutter v0.2.1,進一步簡化接入流程,可以簡單三步接入現有專案,開啟由JS編寫的MXFlutter頁面。歡迎小夥伴接入嚐鮮。可以安裝編譯好的 Android 的包來體驗
MXFlutter 是一套基於 JavaScript 的 Flutter 動態化框架,是目前開源的最完整可用的動態化方案,它用極類似Dart的開發方式,通過編寫JavaScript 程式碼,來開發 Flutter 應用。程式碼開源在 MXFlutter Github ,更多細節在 基於JavaScript的Flutter框架詳細介紹。
v0.2.1版本新特性
- 升級適配 Flutter 1.17.0 ,對應Channel stable tag:v1.17.0
- 支援Packages
- dio
- pull_to_refresh
- cached_network_image
- shared_preferences
- 支援MessageChannel
- 效能和穩定性優化,Bug Fix
MXFlutter Roadmap
總體目標和方向
- 使用JS開發,擴充套件 Flutter 的開發陣營,實現 Flutter 動態化,
- 支援業務由 Dart 開發,使用mxjsbuilder編譯為JS直接執行,實現同一套 Dart 程式碼同時支援 AOT 編譯為 Native APP,也可以編譯為JS支援動態化。
MXFlutter 當前因為工程量龐大,人力有限,還有很多需要逐步修改優化的地方,更新計劃參照 MXFlutter Roadmap
MXFlutter 接入指南
mxflutter 是一個標準的 Dart package,可以按照 Dart 引入 package 的方式接入,步驟非常簡單。在開始接入之前,執行體驗 mxfltuter 的兩個例子,對接入會有幫助,一個是示例豐富但比較複雜的例子,在
mxflutter v0.2.1 對應Flutter 1.17.0 (Channel stable tag:v1.17.0)
三步接入MXFlutter
1. 新增依賴
dependencies:
mxflutter: ^0.2.1
複製程式碼
因為mxflutter在快速迭代,推薦 fork 在 github 的主庫 github.com/mxflutter/m… 來接入,方面自己修改和定期從主庫的更新。
dependencies:
mxflutter:
git:
url: https://github.com/mxflutter/mxflutter.git
path: mxflutter/
複製程式碼
2. 拷貝示例JS程式碼檔案,配置JS程式碼資源引入
第一步拷貝JS程式碼檔案:mxflutter 主庫提供了JS程式碼模版,拷貝主庫 mxflutter/example/mxflutter_js_src (github.com/mxflutter/m…) 資料夾到你的工程目錄,和pubspec.yaml檔案同級。
第二步在 pubspec.yaml 檔案中引入 mxflutter_js_src 程式碼資原始檔夾
flutter:
assets:
- mxflutter_js_src/
複製程式碼
特別注意:第一步拷貝的資料夾和第二步匯入的資源是配套的,因為 pubspec.yaml 匯入資源時,不會自動匯入子資料夾, 如果你是拷貝的主庫根目錄 github.com/mxflutter/m… 資料夾,要配套按照主庫 pubspec.yaml 的資源配置來引入,學習接入建議使用 mxflutter/example/mxflutter_js_src 的示例
完成後目錄結構應該是這樣的
my_flutter/
├── lib/
│ └── main.dart
└── pubspec.yaml
└── mxflutter_js_src/
│ └── main.js
│ └── home_page.js
│ └── js_dev_demo.js
│ └── mxjsbuilder_demo.js
複製程式碼
3. 在Flutter程式碼中,執行MXFlutter,開啟由JS編寫的頁面
在 main.dart 檔案中,呼叫 runJSApp 啟動JSApp,runJSApp 函式如果不傳任何引數,預設會執行 mxflutter_js_src/mian.js 檔案
//mxflutter
import 'package:mxflutter/mxflutter.dart';
void main() {
//-------1. MXFlutter 啟動---------
MXJSFlutter.getInstance().runJSApp();
runApp(MyApp());
}
複製程式碼
在合適時機,比如使用者點選介面時,開啟JS頁面。
onTap: () {
//-------2. MXFlutter push 一個使用MXFlutter框架編寫的頁面
Navigator.push(
context,MaterialPageRoute(
builder: (context) => MXJSPageWidget(
jsWidgetName: "MXJSWidgetHomePage")));
}
複製程式碼
上面程式碼 MXJSPageWidget 的引數 jsWidgetName: "MXJSWidgetHomePage",在mxflutter_js_src/main.js MyApp::createJSWidgetWithName 函式中使用,用來標示開啟哪個JS頁面。
bingo 如果順利的話,基本得接入工作已經完成,你應該可以開啟一個經典的 Flutter 示例頁面了。接下來可以嘗試修改下 mxflutter_js_src/ 資料夾下的JS檔案,可以看到 UI 變化。
更多易用的配置
iOS模擬器熱過載支援
在 github.com/mxflutter/m… 主庫iOS工程或者主庫 mxflutter/example/ 目錄的例子中,AppDelegate.m 檔案詳細註釋瞭如果開啟模擬器熱過載。拷貝setupMXFlutterJSPath 函式,在 Flutter 外掛註冊 [GeneratedPluginRegistrant registerWithRegistry:self]; 之前呼叫即可
- (void)setupMXFlutterJSPath{
///mxflutter js程式碼模擬器熱過載支援
///把JS檔案重定向到本地地址,簡單支援模擬器JS檔案熱過載,
///僅支援模擬器環境使用
///*釋出版本的熱更新,也使用同樣API設定為你的JS程式碼下載目錄
#if TARGET_IPHONE_SIMULATOR
//業務JS程式碼的熱過載
NSString *jsAppPath = nil;
NSArray *jsAppSearchPathList = nil;
///mxflutter framework的開發者用來加快除錯,如不需要修改mxflutter jsframework,無需設定jsFramewrokPath
NSString *jsFramewrokPath = nil;
///1. 可以直接修改定位到絕對路徑,但多人協作開發時,每個人路徑不同需要,需要都配置,推薦第二種方法,配置PROJECT_DIR
///jsFramewrokPath = @“/Volumes/Data/Work/mxflutter2/mxflutter/js_lib”;
///jsAppPath = @"/Volumes/Data/Work/mxflutter2/mxflutter_js_src/"
///2. 可以配置PROJECT_DIR,把JS程式碼路徑地址重定向到開發機iMac地址,用來支援模擬器熱過載,支援多人協同,配置PROJECT_DIR方法如下。
///XCode -> Build Settings -> Preprocessor Macros : Debug下增加 PROJECT_DIR=@\""$PROJECT_DIR\/"\"
///這是github https://github.com/TGIF-iMatrix/mxflutter.git 下的 flutter/example/ios 工程為例子,js_lib的
///物理路徑配置如下
#ifdef PROJECT_DIR
//可以根據自己的工程部署調整相對路徑
jsAppPath = [PROJECT_DIR stringByAppendingPathComponent:@"../mxflutter_js_src/"];
//
jsAppSearchPathList = @[
[jsAppPath stringByAppendingPathComponent:@"app_demo/"],[jsAppPath stringByAppendingPathComponent:@"mxjsbuilder_demo/"]
];
jsFramewrokPath = [PROJECT_DIR stringByAppendingPathComponent:@"../../js_lib/"];
#endif
//可以呼叫[MXFlutterPlugin setJSFramewrokPath:jsFramewrokPath]; 設定jsframework到Documents你的下載目錄,支援framework的熱更新
if (jsFramewrokPath.length > 0) {
[MXFlutterPlugin setJSFramewrokPath:jsFramewrokPath];
}
if (jsAppPath.length > 0) {
[MXFlutterPlugin setJSAppPath:jsAppPath jsAppSearchPathList:jsAppSearchPathList];
}
#endif
}
複製程式碼
APP Demo示例截圖:
先看看使用效果,以下截圖是在MXFlutter框架下用JS開發,可以把上面的原始碼下載下來,裡面有完整的JS程式碼示例:
單頁面演示
下面是UI截圖對應的JS程式碼,沒錯,你沒有眼花,這個是 JavaScript 程式碼,可以在 MXFlutter 的執行時庫上渲染出 Flutter 的UI,(是不是很像Flutter裡面的元件程式碼)!
class JSPestoPage extends MXJSWidget {
constructor() {
super("JSPestoPage");
this.recipes = recipeList;
}
build(context) {
let statusBarHeight = 24;
let mq = MediaQuery.of(context);
if (mq) {
statusBarHeight = mq.padding.top
}
let w = new Scaffold({
appBar: new AppBar({
title: new Text("Pesto Demo")
}),floatingActionButton: new FloatingActionButton({
child: new Icon(new IconData(0xe3c9)),onPressed: function () {
},}),body: new CustomScrollView({
semanticChildCount: this.recipes.length,slivers: [
//this.buildAppBar(context,statusBarHeight),
this.buildBody(context,],//body:this.buildItems()[0]
});
return w;
}
buildAppBar(context,statusBarHeight) {
return SliverAppBar({
pinned: true,expandedHeight: _kAppBarHeight,actions: [
IconButton({
icon: new Icon(new IconData(1)),tooltip: 'Search',onPressed: function () {
},flexibleSpace: LayoutBuilder({
builder: function (context,constraints) {
size = constraints.biggest;
appBarHeight = size.height - statusBarHeight;
t = (appBarHeight - kToolbarHeight) / (_kAppBarHeight - kToolbarHeight);
extraPadding = new Tween({ begin: 10.0,end: 24.0 }).transform(t);
logoHeight = appBarHeight - 1.5 * extraPadding;
return Padding({
padding: EdgeInsets.only({
top: statusBarHeight + 0.5 * extraPadding,bottom: extraPadding,child: Center({
child: new Icon(new IconData(1))
}),});
},});
}
buildBody(context,statusBarHeight) {
let mediaPadding = EdgeInsets.all(0);
let mq = MediaQuery.of(context);
if (mq) {
mediaPadding = MediaQuery.of(context).padding;
}
let padding = EdgeInsets.only({
top: 8.0,left: 8.0 + mediaPadding.left,right: 8.0 + mediaPadding.right,bottom: 8.0
});
return new SliverPadding({
padding: padding,sliver: new SliverGrid({
gridDelegate: new SliverGridDelegateWithMaxCrossAxisExtent({
maxCrossAxisExtent: _kRecipePageMaxWidth,crossAxisSpacing: 8.0,mainAxisSpacing: 8.0,delegate: new SliverChildBuilderDelegate(
function (context,index) {
let recipe = this.recipes[index];
let w = new RecipeCard({
recipe: recipe,onTap: function () { showRecipePage(context,recipe); },});
return w;
},{
childCount: this.recipes.length,});
}
複製程式碼
專案演示
原始碼中還有更豐滿的示例,高仿知乎頁面JSFlutter版,可以點此進入檢視程式碼:
下圖是對應的UI,已經接近線上上版直接使用了:
聯絡我們
當前 MXFlutter 處於 Beta版本,因為工程量龐大,人力有限,還有很多需要逐步修改優化的地方,目前在高速迭代中,使用 MXFlutter 過程中有任何問題,可以加群交流 QQ群:747535761