返回

告别包大小烦恼:动态更新 Flutter 产物,解锁轻盈体验

Android

Flutter,风靡一时的跨平台开发框架,凭借其构建精美且原生应用的能力,备受开发者青睐。然而,将 Flutter 模块嵌入原生应用时,难免会为 apk 带来越来越大的包大小。这些包体积膨胀的罪魁祸首,除了 Flutter SDK 引入的源码,还有随着业务发展而不断增长的应用代码和资源。这对于用户来说,意味着更长的下载和安装时间,以及对存储空间的更大占用。对于开发者而言,频繁的版本更新也带来无穷无尽的烦恼。

动态更新机制应运而生,它通过将 Flutter 产物分拆成更小的模块,按需下载和更新,有效解决了包大小和版本更新的痛点。

具体实现上,我们可以将 Flutter 产物拆分为 base 模块和业务模块。base 模块包含 Flutter 引擎和核心依赖,业务模块则承载具体的业务逻辑和界面。在应用启动时,仅加载 base 模块,按需再下载业务模块。这样做既减轻了 apk 的初始包大小,又保证了应用的核心功能能够快速启动。

热更新和热修复是动态更新机制的两大杀手锏。热更新允许我们在不发布新版本的情况下,对业务模块进行更新。这对于修复紧急 bug 或发布新特性十分便捷。热修复则更进一步,它可以在应用运行时对代码进行修改,从而实现无缝修复。

Flutter 提供了完善的动态更新 API,使开发者能够轻松地将动态更新机制集成到应用中。

要实现动态更新,需要以下步骤:

1. 将 Flutter 产物拆分为 base 模块和业务模块。

2. 在 base 模块的 AndroidManifest.xml 文件中配置动态特性清单。

<manifest ... >
  <dynamic-feature
      android:name="com.example.flutter_feature"
      android:requireFeature="com.example.base" >
    <meta-data
        android:name="flutter_asset_path"
        android:value="flutter_assets" />
  </dynamic-feature>
</manifest>

3. 在业务模块的 build.gradle 文件中配置 Flutter 模块。

dependencies {
  implementation project(':base')
  implementation 'io.flutter:flutter_embedding_release:2.5.4'
}

4. 在应用的 MainActivity 中注册动态特性和处理更新逻辑。

FlutterEngine flutterEngine = new FlutterEngine(this);
flutterEngine.getDartExecutor().executeDartEntrypoint(
    getApplicationContext(),
    "main",
    arguments);

InstallStateUpdateListener listener = new InstallStateUpdateListener() {
  @Override
  public void onStateUpdate(String featureName, int state) {
    if (state == InstallState.INSTALLED) {
      // 动态特性已安装,重新加载 Flutter 引擎
      flutterEngine.reload();
    }
  }
};

getLifecycle().addObserver(listener);

5. 在 Flutter 端实现热更新和热修复。

热更新:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await HotService.registerHotRestartHandler();
  runApp(MyApp());
}

热修复:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await HotService.registerHotReloadHandler();
  runApp(MyApp());
}

动态更新机制的引入,为 Flutter 应用带来了诸多好处:

  • 减小 apk 包大小: 将 Flutter 产物拆分为更小的模块,按需加载,有效减轻了 apk 的初始包大小。
  • 热更新和热修复: 无需发布新版本即可对业务逻辑和代码进行更新和修复,提高了应用的迭代效率和用户体验。
  • 分阶段发布: 通过分阶段发布不同的业务模块,可以根据用户的实际需求进行有针对性的更新,避免全量更新带来的性能和稳定性风险。

在实践中,动态更新机制也有一些需要注意的地方:

  • 模块化设计: 将 Flutter 产物拆分为模块时,需要遵循清晰的模块化设计原则,保证模块之间的低耦合和高内聚。
  • 资源管理: 动态加载的业务模块也会加载相应的资源文件,需要考虑资源文件的管理和优化,避免造成不必要的资源浪费。
  • 兼容性测试: 动态更新机制的引入可能会对应用的兼容性产生影响,需要进行全面的兼容性测试,确保应用在不同设备和系统版本上都能正常运行。

总的来说,动态更新机制是 Flutter 应用拥抱轻盈、敏捷和高迭代效率的不二法门。通过合理的设计和实践,开发者可以充分发挥动态更新机制的优势,打造出更出色的 Flutter 应用。