天天看點

Chimera Flutter Code Push動态化熱更新介紹

Chimera Flutter Code Push動态化熱更新介紹

一、前言

在如今這個程式設計語言百花齊放、百家争鳴的年代,誰能占領移動端App開發的市場,誰就會受到各大廠商的青睐;而在移動端開發領域,如果誰能在跨平台技術上有所突破,那她便更成為百家語言中的花中之魁。衆所周知,Google主導開發的Flutter就以其“多端一緻”和“渲染性能”上的優勢讓其他跨端方案望塵莫及。

Flutter支援現有所知的所有平台(iOS,android,Windows,Linux, Web…),并且支援一套代碼全平台一鍵部署。

然而,出于對性能和安全的考量,Google于2019 年 4 月主動放棄了對于Flutter動态化熱更新的支援,這便成了Flutter這門“超級架構”的美中不足。為了滿足市場的需求和技術的突破,我們維彤科技Chimera團隊從2019年底開始對Flutter動态化更新進行立項研究,截止今年12月初,我們的動态化熱更新SDK和對接方案已告一段落,産品代号也為“Chimera”。

二、什麼是Chimera?

Chimera(奇美拉)是傳說中希臘的一隻神獸,他是一個“混合體”, 他擁有獅子的頭顱,山羊的身軀和蟒蛇的尾巴,并擁有超強的戰鬥力。

我們的産品就像是奇美拉一樣,可以為各個平台提供一套完善的整體嵌入式解決方案,我們的SDK具有易接入,易整合,易編譯的優勢和特點,不管你的app是在開發初期,還是app已經開發完了,都是一鍵無縫接入,同時整個代碼整合和編譯過程都可謂是“傻瓜式”介入。我們的産品提供細粒度熱更新能力,無需等待發版即可實作修複應用線上問題,最終使用者全程無感。

2.1 産品優勢

  • 通用性,即時一鍵接入現有Flutter項目,不會對源App開發程序有任何影響
  • 低成本,動态化對齊 Flutter 生态和正常開發習慣,且可低成本轉化現有的 Flutter 頁面
  • 适用性,修複範圍廣,編譯包體積小,無侵入,無第三方語言介入高性能,保持Flutter App自身性能,無任何性能影響損耗
  • 好服務,一站式整體體驗,支援雙端商業化平台,擁有高可複用的開發體驗
我們的Github開源位址: https://github.com/Waytoon/chimera_flutter_code_push

2.2 實作具體過程:

Chimera Flutter熱更新(CodePush)是一個SDK,已經開發了2年以上,用于Flutter應用程式、代碼熱更新的增強和完善。

如您所知,Google Flutter團隊已宣布,Flutter将不支援其引擎中的代碼推送功能。

Google在這裡提到:

This was previously on our roadmap for 2019. After investigating this in greater detail, we have decided not to proceed with this work for now.

There were several factors that led us to this decision:

  • To comply with our understanding of store policies on Android and iOS, any solution would be limited to JIT code on Android and interpreted code on iOS. We are not confident that the performance characteristics of such a solution on iOS would reach the quality that we demand of our product. (In other words, “it would be too slow”.)
  • There are some serious security concerns. Since these patches would essentially allow arbitrary code execution, they would be extremely attractive malware vectors. We could mitigate this by requiring that patches be signed using the same key as the original package, but this is error prone and any mistake would have serious consequences. This is, fundamentally, the same problem that has plagued platforms that allow execution of code from third-party sources. This problem could be mitigated by integrating with a platform update mechanism, but this defeats the purpose of an out-of-band patching mechanism.
  • There is currently no out-of-the-box open source hosting solution for patching applications, so we would either have to rely on people configuring their Web servers accordingly, or we would have to create integrations for proprietary third-party services, or we would have to create our own bespoke solution. Hosting patches is a space we are not eager to enter. Having people configure their own server leaves them open to making mistakes with potentially serious implications as explained in the previous point about security. Depending on third-party services puts Flutter in an awkward position of having to pick winners and exposes us to the risk of those projects themselves making policy changes that would affect this feature.

是以,Chimera Flutter CodePush在那時就已經進行了初始化和開發:Chimera CodePush是一種雲服務,使Flutter開發人員可以将移動應用程式更新直接部署到其使用者的裝置上。它充當中央存儲庫的角色,開發人員可以将更新釋出到該存儲庫,并且應用程式可以從中查詢更新。在解決錯誤和/或添加不需要重新建構二進制檔案并通過各自的應用商店重新分發二進制檔案的小功能時,這使您可以與使用者群建立更具确定性和直接的參與度模型。

Chimera可以将捆綁包中的UI / Logic / …(所有您想要的)更改分發給使用者,方法類似于其他開源熱更新Project,但是又有所不同。通過內建Flutter Chimera,您可以釋出所有應用程式頁面,而無需等待應用程式的下一個釋出日期。 Chimera提供了一個出色的編譯器,它可以用作轉換,運作,更新Flutter頁面/應用程式全新魔術工具。我們的SDK基于Dart原生語言,沒有使用任何第三方語言做任何開發,是以使用我們的SDK對于flutter開發者非常友好,對您來說,沒有任何的學習成本,可以說是一鍵秒上手!

要開始使用Chimera CodePush,請參考本文檔,如果您想從源代碼建構/貢獻項目,請閱讀以下步驟。

Chimera SDK将支援所有以flutter編寫的應用程式,請毫不猶豫地開始使用此超級代碼推送SDK。

Dev Setup

2.3 DEV Setup

現在開始:

🚩 首先你可能需要先成為一個出色的Flutter程式員或者是一面flutter程式設計愛好者,像我一樣:-),主要是需要熟悉Flutter程式設計,還有一顆喜歡鑽研和學習的心。

設定Flutter代碼環境:here.

你需要一個用的得手的 IDE, 推薦使用Android Studio 或 VSCODE.

注意:在git克隆此倉庫之前,最好安裝“ Git Large File Storage”(https://git-lfs.github.com/)。

它可以幫助您處理和同步大檔案,以避免任何資料流丢失。

切記要安裝 http-server,因為後續的工作需要http-server:
brew install http-server
           

大殺器在這裡,我們的編譯器!這個編譯器便是主要的工具來服務Chimera CodePush。

# 編譯工具下載下傳連結
下載下傳 link:
https://github.com/Waytoon/chimera_flutter_code_push/releases/download/v1.0.0/rust_compile

           

對于中國使用者,您可以參考以下說明連結以加快GitHub檔案的下載下傳速度。

Speedy access github

以下環境目前SDK不支援::

  1. Windows
重要的事情:編譯器運作時需要聯網。全面支援Mac,包括M1.

🏁 請檢查您計算機上的運作時環境。 Chimera基于Flutter最新的穩定版本。并且SDK将來會繼續支援最新的穩定Flutter版本。

https://flutter.dev/docs/development/tools/sdk/releases?tab=macos(opens new window)

我們使用的flutter版本(stable版本)

 ~/Desktop/tool  flutter --version                      
Flutter 1.22.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 9b2d32b605 (6 weeks ago) • 2021-01-22 14:36:39 -0800
Engine • revision 2f0af37152
Tools • Dart 2.10.5
           
如果你現在使用的是flutter 2,請先切換到

flutter 1.22.6 stale

切換方法 請在終端運作

flutter downgrade

2.4 使用 CodePush SDK

  1. 首先運作

    mkdir test

    建立一個

    test

    檔案夾。如下圖:
    Chimera Flutter Code Push動态化熱更新介紹

    cd test

    進入test目錄建立一個

    hello

    項目:

    flutter create hello

    [外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-L3mt7DNR-1615879354290)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicr6Hbv2yGgY5DIVo.png)]

    hello

    目錄結構如下:
    .hello folder
    ├── README.md
    ├── android
    ├── hello.iml
    ├── ios
    ├── lib
    ├── pubspec.lock
    ├── pubspec.yaml
    └── test
               

2.用IDE打開

hello

這個項目:

Chimera Flutter Code Push動态化熱更新介紹

這裡一定要注意!! 使用IDE調試一次

hello

這個項目,不管是使用模拟器還是真機,以下我們使用模拟器作為示例示範。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-2pbYEy7t-1615879354294)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicE4PXYHjkwgfhvlT.png)]

  1. 很重要的一步下載下傳我們的編譯器,連結:

    https://github.com/Waytoon/chimera_flutter_code_push/releases/download/v1.0.0/rust_compile

請注意檢視并關注release版塊的release檔案的釋出,最近一段時間,我們會每晚更新一次編譯器。

下載下傳到一個指定目錄,随意給一個名字,我們就用

tool

吧:

Chimera Flutter Code Push動态化熱更新介紹

然後打開終端terminal,進入編譯器的目錄,運作指令

chmod 777 rust_compile

,以使得編譯器有權限可以運作

下一步在終端中運作

./rust_compile

Chimera Flutter Code Push動态化熱更新介紹
第一次運作編譯器,會生成配置檔案

config.yaml

  1. 運作後會提示配置

    config.yaml

    ,如上圖所示。

    打開

    config.yaml

    并配置如下内容:
# Project path
  projectPath: /Users/ryanliu/Desktop/test/hello #修改成hello的目錄
  # Flutter SDK
  flutterSdkPath: /Users/ryanliu/development/flutter #修改目前flutter環境的SDK目錄
  # Compile cache path
  buildCachePath: /Users/ryanliu/Desktop/temp/dart_compile_cache #設定一個專門目錄儲存dart_compile_cache
  # FTP
  #ftpConfig: 192.168.80.141|root|123456  此處可忽略
           
  1. 然後在終端中再次運作

    ./rust_compile

    執行我們的編譯過程。

    大概2-5分鐘的樣子,就可以得到下面的畫面結果,編譯的産物

    hello.bin

    在項目

    hello/assets/

    目錄下,同時多出了

    wtbase

    庫目錄。
    Chimera Flutter Code Push動态化熱更新介紹
    我們可以看到

    hello

    檔案夾目錄變化為,注意目錄裡多出了兩個新的檔案夾

    assets

    wtbase

    ├── README.md
    ├── android
    ├── assets
    ├── build
    ├── hello.iml
    ├── ios
    ├── lib
    ├── pubspec.lock
    ├── pubspec.yaml
    ├── test
    └── wtbase
               
  2. 下面這一步非常重要! 配置

    wtbase/pubspec.yaml

    dependencies

    修改flutter_code_push的引導路徑為以下:
flutter_code_push:
             git:
               url: https://github.com/Waytoon/chimera_flutter_code_push.git
               path: flutter_code_push
           

原配置:

Chimera Flutter Code Push動态化熱更新介紹

修改之後:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-42Pza2NI-1615879354298)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicZHQtr5qJSRyuXvP.png)]

記得點一下上面的

pub get

,或者在terminal裡輸入

flutter pub get

.

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-Meq4QDxJ-1615879354299)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicA2RCGdQWJl7yBPc.png)]

  1. 然後修改

    hello/pubspec.yaml

    ,在

    dependencies

    添加如下:

wtbase: path: ./wtbase

并将

dependencies

下的其他依賴庫剪切複制到

wtbase/pubspec.yaml’的

dependencies`下,最終效果如下:

hello/pubspec.yaml

:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-VRSJYg26-1615879354300)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicimage-20210307151156273.png)]

hello/wtbase/pubspec.yaml

:

Chimera Flutter Code Push動态化熱更新介紹

記得運作

flutter pub get

,或者點選

Pub get

按鈕。

注意事項: 請先運作

wtbase

目錄的

Pub get

, 然後在運作

hello

項目的

Pub get

。這樣做的目的是為了保證項目依賴庫的版本号保持一緻性。
截止到這裡,初步的SDK配置工作已經完成,下面我們講解如何在我們的source code裡使用和實作熱更新。
  1. 現在在

    hello/lib

    目錄下建立

    MyApp.dart

    檔案,Source code如下:
import 'package:flutter/material.dart';
            import 'package:dio/dio.dart';
            
            void initApp() {
              runApp(MyApp());
            }
            
            class MyApp extends StatelessWidget {
              // This widget is the root of your application.
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  title: 'Flutter Demo',
                  theme: ThemeData(
                    // This is the theme of your application.
                    //
                    // Try running your application with "flutter run". You'll see the
                    // application has a blue toolbar. Then, without quitting the app, try
                    // changing the primarySwatch below to Colors.green and then invoke
                    // "hot reload" (press "r" in the console where you ran "flutter run",
                    // or simply save your changes to "hot reload" in a Flutter IDE).
                    // Notice that the counter didn't reset back to zero; the application
                    // is not restarted.
                    primarySwatch: Colors.blue,
                    // This makes the visual density adapt to the platform that you run
                    // the app on. For desktop platforms, the controls will be smaller and
                    // closer together (more dense) than on mobile platforms.
                    visualDensity: VisualDensity.adaptivePlatformDensity,
                  ),
                  home: MyHomePage(title: 'Flutter Demo Home Page'),
                );
              }
            }
            
            class MyHomePage extends StatefulWidget {
              MyHomePage({Key key, this.title}) : super(key: key);
            
              // This widget is the home page of your application. It is stateful, meaning
              // that it has a State object (defined below) that contains fields that affect
              // how it looks.
            
              // This class is the configuration for the state. It holds the values (in this
              // case the title) provided by the parent (in this case the App widget) and
              // used by the build method of the State. Fields in a Widget subclass are
              // always marked "final".
            
              final String title;
            
              @override
              _MyHomePageState createState() => _MyHomePageState();
            }
            
            class _MyHomePageState extends State<MyHomePage> {
              int _counter = 0;
              String _response;
            
              void _incrementCounter() {
                setState(() {
                  // This call to setState tells the Flutter framework that something has
                  // changed in this State, which causes it to rerun the build method below
                  // so that the display can reflect the updated values. If we changed
                  // _counter without calling setState(), then the build method would not be
                  // called again, and so nothing would appear to happen.
                  _counter++;
                });
              }
            
              void _getHttp() async {
                try {
                  Response response = await Dio().get("http://www.google.com");
                  setState(() {
                    String temp = '$response';
                    for (var i = 0; i < 10; ++i) {
                      temp = '$i' + temp;
                    }
                    _response = temp.substring(0, 100);
                  });
                } catch (e) {
                  print(e);
                }
              }
            
            
              @override
              void initState() {
                _getHttp();
                super.initState();
              }
            
              @override
              Widget build(BuildContext context) {
                // This method is rerun every time setState is called, for instance as done
                // by the _incrementCounter method above.
                //
                // The Flutter framework has been optimized to make rerunning build methods
                // fast, so that you can just rebuild anything that needs updating rather
                // than having to individually change instances of widgets.
                return Scaffold(
                  appBar: AppBar(
                    // Here we take the value from the MyHomePage object that was created by
                    // the App.build method, and use it to set our appbar title.
                    title: Text(widget.title),
                  ),
                  body: Center(
                    // Center is a layout widget. It takes a single child and positions it
                    // in the middle of the parent.
                    child: Column(
                      // Column is also a layout widget. It takes a list of children and
                      // arranges them vertically. By default, it sizes itself to fit its
                      // children horizontally, and tries to be as tall as its parent.
                      //
                      // Invoke "debug painting" (press "p" in the console, choose the
                      // "Toggle Debug Paint" action from the Flutter Inspector in Android
                      // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
                      // to see the wireframe for each widget.
                      //
                      // Column has various properties to control how it sizes itself and
                      // how it positions its children. Here we use mainAxisAlignment to
                      // center the children vertically; the main axis here is the vertical
                      // axis because Columns are vertical (the cross axis would be
                      // horizontal).
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text(
                          'You have pushed the button this many times:',
                        ),
                        Text(
                          '$_counter',
                          style: Theme.of(context).textTheme.headline4,
                        ),
                        Text(
                       'Server Response:\n$_response'
                        )
                   ],
                    ),
               ),
                  floatingActionButton: FloatingActionButton(
                    onPressed: _incrementCounter,
                    tooltip: 'Increment',
                    child: Icon(Icons.add),
                  ), // This trailing comma makes auto-formatting nicer for build methods.
                );
              }
            }
           

添加完這個檔案後,記得運作

flutter pub get

一下,確定依賴正确導入。

然後我們修改

main.dart

檔案如下:

```dart
        import 'package:hello/MyApp.dart';
        import 'package:wtbase/wtbase.dart';
        import 'package:flutter/material.dart';
        
        void main() async {
          WidgetsFlutterBinding.ensureInitialized();
        
          bool isNative = false;
          if (isNative) {
            initApp();
          } else {
            String downloadUrl = "http://yourlocalhost/hello.bin";
            readCode = WTAnalysisReadCode();
            await readCode.loadFile(downloadUrl);
            readCode.executeMethod(
                'package:hello/MyApp.dart', 'initApp');
          }
        }
        ```
           
請注意

downloadUrl

現在僅支援内網測試。

downloadUrl

需要以

http://192.168

開頭。

如需支援外網請求,請聯系

[email protected]

另一個至關重要的步驟:

打開終端terminal,進入

hello/assets

目錄:

Chimera Flutter Code Push動态化熱更新介紹

然後在terminal輸入:

http-server -c -1

結果如下:

Chimera Flutter Code Push動态化熱更新介紹

複制

http-server

下面的連結,我的是

http://192.168.80.115:8080

,用來修改

main.dart

裡的

String downloadUrl = "http://yourlocalhost/hello.bin";
           

修改成:

String downloadUrl = "http://192.168.80.115:8080/hello.bin";
           

到此為止整個的接入過程已經告一段落了。

  1. 下面的事情就是從IDE運作一下你的APP,方法就是點選那個綠蟲子。

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-UUbFvJ4D-1615879354303)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicimage-20210307142840043.png)]

不出任何意外,IDE的編譯不會出現任何問題。模拟器上的顯示是這樣的。

Chimera Flutter Code Push動态化熱更新介紹

DE的

debug console log

如下:

Launching lib/main.dart on Android SDK built for x86 in debug mode...
            Running Gradle task 'assembleDebug'...
            ✓ Built build/app/outputs/flutter-apk/app-debug.apk.
            Installing build/app/outputs/flutter-apk/app.apk...
            Waiting for Android SDK built for x86 to report its views...
            Debug service listening on ws://127.0.0.1:65046/r1MGSW-wdg4=/ws
            Syncing files to device Android SDK built for x86...
            W/m.example.hell( 6898): Accessing hidden method Lsun/misc/Unsafe;->getUnsafe()Lsun/misc/Unsafe; (greylist,core-platform-api, linking, allowed)
            W/m.example.hell( 6898): Accessing hidden method Lsun/misc/Unsafe;->objectFieldOffset(Ljava/lang/reflect/Field;)J (greylist,core-platform-api, linking, allowed)
            W/m.example.hell( 6898): Accessing hidden method Lsun/misc/Unsafe;->compareAndSwapObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z (greylist, linking, allowed)
            W/m.example.hell( 6898): Accessing hidden method Lsun/misc/Unsafe;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V (greylist, linking, allowed)
            D/EGL_emulation( 6898): eglMakeCurrent: 0xd7a8e900: ver 3 0 (tinfo 0xdaf0f820)
            D/eglCodecCommon( 6898): setVertexArrayObject: set vao to 0 (0) 1 0
            I/flutter ( 6898): download file!
            I/flutter ( 6898): vmClassName: MyApp className: WTStatelessWidget1
            I/flutter ( 6898): vmClassName: MyHomePage className: WTStatefulWidget1
            I/flutter ( 6898): vmClassName: _MyHomePageState className: WTState1
           
  1. 後面的事情就是任由你自己發揮了。比如我們修改

    MyApp.dart

    裡的代碼試一下。修改

    floatingActionButton

    的icon試一下吧:
floatingActionButton: FloatingActionButton(
                    onPressed: _incrementCounter,
                    tooltip: 'Increment',
                    child: Icon(Icons.add),
                  ),
           

Icons.add

修改為

Icons.home

。完成後是這樣的:

floatingActionButton: FloatingActionButton(
                    onPressed: _incrementCounter,
                    tooltip: 'Increment',
                    child: Icon(Icons.home),
                  ),
           

儲存你所做的修改,然後回到terminal,進入你的編譯器目錄,運作

./rust_compile

Chimera Flutter Code Push動态化熱更新介紹

運作這個指令後,等待一段時間,最終效果如下:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-WiVisZSB-1615879354304)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPicimage-20210307144050787.png)]

這裡親請注意了,我們到此不需要IDE來做什麼了,隻需要在模拟器裡關掉目前運作的app,重新打開它,你就會發現它變成了下面的樣子:

Chimera Flutter Code Push動态化熱更新介紹

再次強調一下到此為止我們上面的這一步操作沒有使用IDE的任何功能,我們隻是用我們自己的編譯器編譯了新的

hello.bin

檔案,然後通過模拟器遠端加載了這個

bin

檔案。

###這就是一個可以完整熱更新的APP了。

到此為止,你已經開發了一個帶有熱更新功能的App了,是不是很神奇?! 你現在可以随意去改一些代碼試試,改過你的代碼後記得要再次編譯哦(重複第10步)。

喜歡的話就給我們點個星星吧✨!

##注意事項:

第一: 對于android app釋出:

對于安卓App開發,需要提前給App賦予網絡和存儲權限,這點很重要。修改

hello/app/src/main/AndroidManifest.xml

Chimera Flutter Code Push動态化熱更新介紹

第二: 對于iOS app釋出:

對于iOS App開發:需要在 “Architectures” 設定中添加, “arm64 & x86_64” 。否則你編譯的時候會報出錯誤。

更改步驟如下:

最初預設是這樣的:

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-V3hWSd9a-1615879354306)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPickLszR3b8veMWt2T.png)]

修改過程:首先點

other

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-D5DN5MWd-1615879354308)(https://raw.githubusercontent.com/Waytoon/Chimera_media/main/uPic5V9B8kRhQreAuFp.png)]

會出現以下視窗:

Chimera Flutter Code Push動态化熱更新介紹
然後點

+

出現以下:
Chimera Flutter Code Push動态化熱更新介紹
在文本框裡輸出

arm64

。 再次點

+

,添加

x86_64

;會有兩項被添加。
Chimera Flutter Code Push動态化熱更新介紹
最後選中

$(ARCHS_STANDARD)

,點選上圖中的

-

,删除

$(ARCHS_STANDARD)

最終效果:

Chimera Flutter Code Push動态化熱更新介紹
注意,如果iOS編譯的時候,如果XCODE報

x86_64

.a

檔案相關的編譯錯誤的時候,請将

Architectures

x86_64

删除掉,再次運作XCODE釋出。删除

x86_64

将不支援iOS模拟器了。

提醒,如果你想部署APP到iPhone真機并不用連接配接iPhone資料線到電腦的話,請Profile你的APP到手機上,XCODE快捷鍵是

⌘ + i

對于Android apk釋出,可能會遇到的問題:

在釋出

android apk

的時候,如果你使用

flutter build apk

的時候會報錯如下:

This application cannot tree shake icons fonts. It has non-constant instances of IconData at the following locations:
  - file:///Users/ryanliu/Desktop/test/hello/wtbase/lib/generate/mapping/WTVMIconData.dart:31:12
           

請使用如下執行指令釋出

apk

:

flutter build apk --no-tree-shake-icons
           

你就不會再遇見上面那個錯誤了。

相關的介紹資料

更多的資訊我們随後會放在一下連結:

  • Chimera Flutter Code Push Instruction
  • Chimera Flutter Code Push動态化熱更新介紹

🛣️ 我們 2021 的計劃

  • 春天·開源在 2021的高鐵上
    • 項目 啟動 ✅
    • 介紹文檔 ✅
    • Github 開源 https://github.com/Waytoon/chimera_flutter_code_push ✅
  • 下一代的神奇 V2 in 2021
    • 實作差異化更新
    • 全面AOT支援
    • AI 智能編譯器

⚠️不支援的内容??

  • 現在不謙虛的說我們支援了所有的Flutter文法和Pub庫.
  • 可能會有一些意外的bug,我們也不想,那就請大家一起去把它們殺光吧,德瑪西亞!

🔧如果你喜歡可以加入我們!

我們在此熱烈歡迎來自五湖四海的兄弟姐妹加入我們,我們需要社群裡大家的支援和幫忙,真誠歡迎大家來到我們的github首頁:https://github.com/Waytoon/chimera_flutter_code_push 歡迎大家點贊轉發評論。再次感謝!

歡迎掃描下面的碼子加入我們:

  • 可以添加SDK群主WX: 搜尋

    novolei