开启Flutter热更新之旅

2,405 阅读3分钟

感谢 @Waytoon 带来的新工具Github传送门

千言万语无以表达心潮之澎湃,直接上体验教程与踩坑。

1. 拉取项目

访问GitHub拉取最新的main分支代码:

git clone https://hub.fastgit.org/Waytoon/chimera_flutter_code_push 

2. 下载compile工具

https://hub.fastgit.org/Waytoon/chimera_flutter_code_push/releases

下载rust_compile工具后复制到chimera_flutter_code_push/compile_tool/目录下,覆盖原来的文件,并且为新的rust_compile工具添加执行权限chmod +x rust_compile

3. 运行hello项目

用IDE打开chimera_flutter_code_push/example_project/hello项目,然后删除wtbase目录。接下来进入chimera_flutter_code_push/compile_tool/目录,编辑config.yaml,如下:

environment:
  # hello项目的目录
  projectPath: /Users/apple/Desktop/chimera_flutter_code_push/example_project/hello
  # 机器上的flutter sdk目录
  flutterSdkPath: /Users/apple/Documents/flutter 
  # 随便设置一个临时目录放编译缓存文件
  buildCachePath: /Users/apple/Desktop/hel_cache
  # FTP 暂时不需要
  # ftpConfig: 192.168.80.141|root|123456

然后直接执行./rust_compile,如果有以下输出则表示成功:

Start compiling!
projectPath: /Users/apple/Desktop/chimera_flutter_code_push/example_project/hello
pubspec parse complete!~
Compiled successfully! Generate Bin path /Users/apple/Desktop/chimera_flutter_code_push/example_project/hello/assets/hello.bin
Compilation completed!

4. 准备文件服务器

如果是mac用户,可以直接使用python命令启动一个静态服务。注意,该命令会直接将当前目录作为服务的根目录,所以需要先cd /Users/apple/Desktop/chimera_flutter_code_push/example_project/hello/assets,然后执行python -m SimpleHTTPServer 8000,其中8000指服务端口

其他机器可以考虑用nodejs等启动一个静态服务器,只要将hello/assets目录作为根目录即可

接下来就是编辑hello/lib/main.dart文件,将downloadUrl改为自己的http服务

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://192.168.0.11:8000/hello.bin";
    readCode = WTAnalysisReadCode();
    await readCode.loadFile(downloadUrl);
    readCode.executeMethod(
        'package:hello/MyApp.dart', 'initApp');
  }
}

4. 验证测试

  • (1)hello项目根目录会自动创建wtbase目录,无需修改
  • (2)在IDE直接运行hello项目,如果运行成功,则可以看到flutter的hello world页面
  • (3)用IDE任意修改MyApp.dart代码,然后执行./rust_compile后重新在终端打开hello app,然后查看效果
  • (4)以后热修复的操作就是:直接改bug + ./rust_compile + 等待用户重启app

5. 坑

  • 直接用IDE运行hello项目时报错:

Running Gradle task 'assembleDebug'...                                 ⣷                                  wtbase/lib/generate/mapping/WTVMScaffold.dart:44:31: Error: Getter not found: 'DragStartBehavior'.
    drawerDragStartBehavior = DragStartBehavior.start,                  
                              ^^^^^^^^^^^^^^^^^                         
wtbase/lib/generate/mapping/WTVMFloatingActionButton.dart:97:19: Error: Getter not found: 'SystemMouseCursors'.
    mouseCursor = SystemMouseCursors.click,                             
                  ^^^^^^^^^^^^^^^^^^                                    
wtbase/lib/generate/mapping/WTVMTextStyle.dart:72:30: Error: 'ui.Shadow' can't be used as a type because 'ui' doesn't refer to an import prefix.
      shadows: shadows?.cast<ui.Shadow>(),                              
                             ^^^^^^^^^                                  
wtbase/lib/generate/mapping/WTVMTextStyle.dart:73:40: Error: 'ui.FontFeature' can't be used as a type because 'ui' doesn't refer to an import prefix.
      fontFeatures: fontFeatures?.cast<ui.FontFeature>(),               
                                       ^^^^^^^^^^^^^^                   
wtbase/lib/generate/mapping/WTVMTextStyle.dart:126:30: Error: 'ui.Shadow' can't be used as a type because 'ui' doesn't refer to an import prefix.
      shadows: shadows?.cast<ui.Shadow>(),                              
                             ^^^^^^^^^                                  
wtbase/lib/generate/mapping/WTVMTextStyle.dart:127:40: Error: 'ui.FontFeature' can't be used as a type because 'ui' doesn't refer to an import prefix.
      fontFeatures: fontFeatures?.cast<ui.FontFeature>(),               
                                       ^^^^^^^^^^^^^^                   
wtbase/lib/generate/mapping/WTVMTextStyle.dart:184:30: Error: 'ui.Shadow' can't be used as a type because 'ui' doesn't refer to an import prefix.
      shadows: shadows?.cast<ui.Shadow>(),                              
                             ^^^^^^^^^                                  
wtbase/lib/generate/mapping/WTVMTextStyle.dart:185:40: Error: 'ui.FontFeature' can't be used as a type because 'ui' doesn't refer to an import prefix.
      fontFeatures: fontFeatures?.cast<ui.FontFeature>(),               
                                       ^^^^^^^^^^^^^^                   
                                                                        
                                                                        
FAILURE: Build failed with an exception. 

解决办法

(1)打开wtbase/lib/generate/mapping/WTVMScaffold.dart 加入代码:import 'package:flutter/gestures.dart';

(2)打开wtbase/lib/generate/mapping/WTVMFloatingActionButton.dart 加入代码:import 'package:flutter/rendering.dart';

(3)打开wtbase/lib/generate/mapping/WTVMTextStyle.dart 加入代码:import 'dart:ui' as ui;

  • 热更新模式isNative=false时打开app白屏

(1)可能是项目带宽不够(不明白热修复走什么带宽然后做什么),这个无解,只能等作者修复

(2)可能是执行rust_compile后的产物破坏了,需要重新拉取chimera_flutter_code_push整个项目,重新再来吧(oh my god!!!!!!!)

(3)其他,别的问题应该还有,期待一步步完善。

  • rust_compile工具问题

(1)执行后没有任何日志输出: 再来几遍吧~

(2)执行报错:重新去下载release中的工具吧

  • 热更新失败或者启动白屏

(1)目前貌似不支持添加showDialog,这个还需要继续验证

最后非常感谢作者Waytoon ~