Flutter性能监控插件flight_recorder的使用

Flutter性能监控插件flight_recorder的使用

Package Logo

Delivering rich, cost-effective, in-context video of your users’ experiences on your app. With just a shake, screenshot, or tap.

安装

运行以下命令:

$ flutter pub add flight_recorder

或者在pubspec.yaml文件中添加依赖项:

dependencies:
  flight_recorder: ^latest_version

前往我们的主要文档了解如何集成和自定义FlightRecorder,或继续阅读以快速入门。

必要的Android项目更改

更新MainActivity以扩展FlutterFragmentActivity

为了使屏幕录制功能正常工作,MainActivity需要继承FlutterFragmentActivity而不是FlutterActivity。更新代码如下:

  1. 打开你的Flutter应用。
  2. 打开文件./android/app/src/main/kotlin/{your app path}/MainActivity.kt
  3. 将导入语句从import io.flutter.embedding.android.FlutterActivity更改为import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.android.FlutterFragmentActivity // 更新

class MainActivity: FlutterActivity() {

// ...
  1. class MainActivity: FlutterActivity() {替换为class MainActivity: FlutterFragmentActivity()
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() { // 更新

// ...

更新minSdkVersion和compileSdkVersion

flight_recorder仅支持从Android SDK版本21开始,并且所需的compileSdkVersion为34。更新这些设置如下:

  1. 打开文件./android/app/build.gradle
  2. 定位到android部分内的defaultConfig部分。
  3. minSdkVersion flutter.minSdkVersion更改为minSdkVersion 21
// ...
android {
    // ...
    default {
        // ...
        minSdkVersion 21  // 更新minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        // ...
  1. minSdkVersion 21下插入compileSdkVersion 34
// ...
android {
    // ...
    default {
        // ...
        minSdkVersion 21
        compileSdkVersion 34 // 插入compileSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        // ...

添加Proguard规则

在Proguard规则中添加以下内容:

-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
  <fields>;
}

如果没有proguard-rules.pro文件,在以下目录创建一个:

android/app/proguard-rules.pro

配置

  1. 打开文件./lib/main.dart,或包含runApp方法调用的文件。
  2. 定位到main()函数。找到runApp方法调用及其传递的Widget,例如MyAppApp等。我们将其称为ROOT WIDGET。如果这个Widget是在你自己的代码中声明的,请跳到步骤3。如果你的main()函数直接返回一个第三方Widget(如MaterialApp),请继续阅读此步骤:
void main() {
  runApp(const MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

你需要将MaterialApp提取到一个单独的Widget中。可以使用VSCode和Refactor菜单轻松完成此任务。

将光标放在Widget符号上,例如MaterialApp,调出Refactor菜单并选择Extract Widget。输入RootWidget或其他名称,然后按Enter

以下是修改后的示例:

void main() {
  runApp(RootWidget());
}

class RootWidget extends StatelessWidget {
  const RootWidget({
    super.key,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Navigation Basics',
      home: FirstRoute(),
    );
  }
}

我们将RootWidget(或你命名的Widget)称为ROOT WIDGET

  1. 转到ROOT WIDGET类的声明。这可能在不同的文件中。

如果ROOT WIDGETApp,则其声明可能如下所示:

class App extends StatelessWidget {

class App extends StatefulWidget {
  1. 在包含ROOT WIDGET类声明的文件顶部添加以下导入语句:
import 'package:flight_recorder/flight_recorder.dart';
import 'package:flight_recorder/screen_recorder.dart';
  1. 如果ROOT WIDGET类继承自StatefulWidget,请转到步骤选项1:向Stateful Root Widget添加SDK

如果类继承自StatelessWidget,请转到步骤选项2:向Stateless Root Widget添加SDK

选项1:向Stateful Root Widget添加SDK

确保你在执行以下操作之前已遵循启动FlightRecorder部分的说明。

这些说明适用于那些main()函数的runApp方法调用返回继承自StatefulWidget的Widget的项目。我们称这个Widget为ROOT WIDGET

  1. 打开包含ROOT WIDGET类声明的文件。这可能是./lib/main.dart

  2. ROOT WIDGET类中找到createState()实现。如果ROOT WIDGETMyApp,这可能看起来像这样:

[@override](/user/override)
State&lt;MyApp&gt; createState() =&gt; _MyAppState();

识别createState()返回的类的名称。我们称其为{ROOT WIDGET STATE SUBCLASS}。转到{ROOT WIDGET STATE SUBCLASS}的类声明。在我们的例子中,这是:

class _MyAppState extends State&lt;MyAppState&gt; {
  1. 在{ROOT WIDGET STATE SUBCLASS}内部,创建final_flightRecorderPlugin常量,并将其设置为FlightRecorder(),如下所示:
class _MyAppState extends State&lt;MyAppState&gt; {

 final _flightRecorderPlugin = FlightRecorder(); // 添加此常量

 // ...

  1. 在{ROOT WIDGET STATE SUBCLASS}内部,实现initState,如下所示,它初始化FlightRecorder。将YOUR_API_KEY替换为你的项目的API密钥。
class _MyAppState extends State&lt;MyAppState&gt; {

 final _flightRecorderPlugin = FlightRecorder();

 // 添加此块
 [@override](/user/override)
 void initState() {
   _flightRecorderPlugin.initFlightRecorder('YOUR_API_KEY', true); // 替换为你的API密钥
   super.initState();
 }

 // ...

  1. 在{ROOT WIDGET STATE SUBCLASS}内部,找到build()方法。build()方法返回一个Widget实例。

你需要用ScreenRecorder包装返回的Widget。ScreenRecorder有一个flightRecorderPlugin属性,你需要将其设置为_flightRecorderPlugin,并将child属性设置为返回build()方法原本返回的Widget。

你可以使用VSCode和Refactor菜单轻松完成此任务。我们将通过一个示例来演示,该示例通过MyWidget()返回单个Widget。无论你的应用程序从build()方法返回什么,原则都是相同的。

[@override](/user/override)
Widget build(BuildContext context) {
  return MyWidget();
}
  1. 将光标放在返回语句之后的符号上(在我们的示例中是MyWidget),调出Refactor菜单并选择Wrap with widget...。输入ScreenRecorder,然后按Enter。这是我们示例的最终状态,你的也应该有ScreenRecorder被返回,并且原始Widget被设置为child属性的值:
[@override](/user/override)
Widget build(BuildContext context) {
 return ScreenRecorder(
   child: MyWidget(),
 );
}
  1. return ScreenRecorder(行后插入新行,然后插入flightRecorderPlugin: _flightRecorderPlugin,,如下所示:
[@override](/user/override)
Widget build(BuildContext context) {
 return ScreenRecorder(
   flightRecorderPlugin: _flightRecorderPlugin, // 插入此行
   child: MyWidget(),
 );
}

选项2:向Stateless Root Widget添加SDK

确保你在执行以下操作之前已遵循启动FlightRecorder部分的说明。

这些说明适用于那些main()函数的runApp方法调用返回继承自StatelessWidget的Widget的项目。我们称这个Widget为ROOT WIDGET

  1. 打开包含ROOT WIDGET类声明的文件。这可能是./lib/main.dart

  2. 定位到ROOT WIDGET类的声明。如果ROOT WIDGETMyApp,这可能看起来像这样:

class MyApp extends StatelessWidget {
  1. ROOT WIDGET类内,在const {ROOT WIDGET}({super.key})声明下方创建对flightRecorderPlugin的引用,如下所示,其中ROOT WIDGETMyApp
class MyApp extends StatelessWidget {
 const MyApp({
  super.key,
 });

 final FlightRecorder flightRecorderPlugin; // 插入
  1. 在同一类内,向ROOT WIDGET函数调用添加required this.flightRecorderPlugin属性:
class MyApp extends StatelessWidget {
 const MyApp({
   super.key,
   required this.flightRecorderPlugin, // 插入
 });

 final FlightRecorder flightRecorderPlugin;
  1. 转到main()方法。更新对你的Widget(例如MyApp())的调用,传递flightRecorderPlugin属性,设置为FlightRecorder(),如下所示:
void main() {
  runApp(RootWidget(
    flightRecorderPlugin: FlightRecorder(), // 插入
  ));
}
  1. ROOT WIDGET类内,在flightRecorderPlugin声明下方插入createElement覆盖,如下所示,将YOUR_API_KEY替换为你的项目的API密钥:
class MyApp extends StatelessWidget {
 const MyApp({
  super.key,
  required this.flightRecorderPlugin,
 });

 final FlightRecorder flightRecorderPlugin;

 // 添加此块
 [@override](/user/override)
 StatelessElement createElement() {
   flightRecorderPlugin.initFlightRecorder('YOUR_API_KEY', true);
   return super.createElement();
 }

 // ...
  1. 在同一类内,找到build()方法。build()方法返回一个Widget实例。

你需要用ScreenRecorder包装返回的Widget。ScreenRecorder有一个flightRecorderPlugin属性,你需要将其设置为flightRecorderPlugin,并将child属性设置为返回build()方法原本返回的Widget。

你可以使用VSCode和Refactor菜单轻松完成此任务。我们将通过一个示例来演示,该示例通过MyWidget()返回单个Widget。无论你的应用程序从build()方法返回什么,原则都是相同的。

[@override](/user/override)
Widget build(BuildContext context) {
 return MyWidget();
}
  1. 将光标放在返回语句之后的符号上(在我们的示例中是MyWidget),调出Refactor菜单并选择Wrap with widget...。输入ScreenRecorder,然后按Enter。这是我们示例的最终状态,你的也应该有ScreenRecorder被返回,并且原始Widget被设置为child属性的值:
[@override](/user/override)
Widget build(BuildContext context) {
  return ScreenRecorder(
    child: MyWidget(),
  );
}
  1. ScreenRecorder(行后插入新行,并插入flightRecorderPlugin: flightRecorderPlugin,,如下所示:
[@override](/user/override)
Widget build(BuildContext context) {
  return ScreenRecorder(
    flightRecorderPlugin: flightRecorderPlugin, // 插入此行
    child: MyWidget(),
  );
}

更多关于Flutter性能监控插件flight_recorder的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter性能监控插件flight_recorder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


Flutter Flight Recorder 是一个用于监控 Flutter 应用程序性能的插件。它可以帮助开发者收集和分析应用程序运行时的性能数据,例如帧率、内存使用、CPU 使用率等。通过使用 Flight Recorder,你可以更好地了解应用程序的性能瓶颈,并进行优化。

安装 Flight Recorder

首先,你需要在 pubspec.yaml 文件中添加 flight_recorder 依赖:

dependencies:
  flutter:
    sdk: flutter
  flight_recorder: ^latest_version

然后运行 flutter pub get 来安装依赖。

基本用法

  1. 初始化 Flight Recorder

    在你的应用程序启动时,初始化 FlightRecorder

    import 'package:flight_recorder/flight_recorder.dart';
    
    void main() {
      FlightRecorder.initialize();
      runApp(MyApp());
    }
    
  2. 开始记录性能数据

    在需要监控性能的地方,启动 FlightRecorder

    FlightRecorder.start();
    
  3. 停止记录并获取数据

    在监控结束后,停止 FlightRecorder 并获取性能数据:

    FlightRecorder.stop();
    var performanceData = FlightRecorder.getPerformanceData();
    print(performanceData);
    

    performanceData 包含了应用程序运行时的各种性能指标,例如帧率、内存使用、CPU 使用率等。

  4. 自定义配置

    FlightRecorder 允许你自定义配置,例如设置采样间隔、启用/禁用特定的性能指标等:

    FlightRecorder.initialize(
      sampleInterval: Duration(milliseconds: 500),
      enableFrameRate: true,
      enableMemoryUsage: true,
      enableCpuUsage: true,
    );
    
  5. 保存和导出数据

    你可以将性能数据保存到文件中,或者通过网络发送到服务器进行进一步分析:

    var performanceData = FlightRecorder.getPerformanceData();
    // 保存到文件
    saveToFile(performanceData);
    // 发送到服务器
    sendToServer(performanceData);
    

示例代码

以下是一个完整的示例,展示如何在 Flutter 应用中使用 FlightRecorder

import 'package:flutter/material.dart';
import 'package:flight_recorder/flight_recorder.dart';

void main() {
  FlightRecorder.initialize(
    sampleInterval: Duration(milliseconds: 500),
    enableFrameRate: true,
    enableMemoryUsage: true,
    enableCpuUsage: true,
  );
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  [@override](/user/override)
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  [@override](/user/override)
  void initState() {
    super.initState();
    FlightRecorder.start();
  }

  [@override](/user/override)
  void dispose() {
    FlightRecorder.stop();
    var performanceData = FlightRecorder.getPerformanceData();
    print(performanceData);
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flight Recorder Example'),
      ),
      body: Center(
        child: Text('Performance Monitoring in Progress...'),
      ),
    );
  }
}
回到顶部