perflutter 0.0.7
perflutter: ^0.0.7 copied to clipboard
A reusable performance tracking package for Flutter navigation.
Perflutter #
Performance when building in Flutter is why it is named Perflutter as one word. Perflutter is a lightweight Flutter package to inspect real navigation performance in-app. It helps you detect dropped frames, estimate FPS, observe memory peaks, and understand user journey flow screen by screen.
Why This Package #
Smoothness is part of product quality. When frames drop:
- animations stutter
- gestures feel delayed
- users feel the app is "heavy" or unstable
Perflutter gives you live, session-level evidence for where performance pressure happens, so you can fix real bottlenecks faster.

Why Frames Matter #
Flutter renders continuously. If UI work or raster work exceeds the frame budget, that frame misses target refresh timing and appears as jank.
- at 60Hz, budget is about
16.67ms - at 120Hz, budget is about
8.33ms - more dropped frames means less smooth experience
This is an early indicator that expensive work is happening on the wrong thread or at the wrong time.
How Perflutter Works #
PerflutterNavigatorObserverlistens to route and tab changes.PerflutterTrackerstarts a screen record for the active route.- Flutter
FrameTimingsamples are collected for the current screen. - Frame, dropped-frame, and memory stats are aggregated.
PerflutterTriggeropens a full report overlay on top of your app.
Installation #
Add dependency:
dependencies:
perflutter: ^0.0.5
Setup Step By Step #
1) Add Navigator Observer #
import 'package:perflutter/perflutter.dart';
MaterialApp(
navigatorObservers: [
PerflutterNavigatorObserver(),
],
home: HomePage(),
);
For MaterialApp.router / AutoRoute:
MaterialApp.router(
routerConfig: _appRouter.config(
navigatorObservers: () => [
PerflutterNavigatorObserver(),
],
),
);
2) Wrap App With Trigger #
import 'package:perflutter/perflutter.dart';
MaterialApp(
builder: (context, child) {
return PerflutterTrigger(
triggerMode: PerflutterTriggerMode.floatingButton,
child: child ?? const SizedBox.shrink(),
);
},
);
3) Open Report #
floatingButton: tap the floatingButton
or
longPress: long-press anywhere to open
Configurable Attributes #
PerflutterTrigger parameters #
child(Widget, required): your app content.enabled(bool, optional, defaulttrue): enables/disables the whole feature.triggerMode(PerflutterTriggerMode?, optional): access entry mode.PerflutterTriggerMode.floatingButtonPerflutterTriggerMode.longPress
Example:
PerflutterTrigger(
enabled: true,
triggerMode: PerflutterTriggerMode.floatingButton,
child: child ?? const SizedBox.shrink(),
)
Other public API you may use directly #
PerflutterNavigatorObserver(): attach to navigator observers for route tracking.PerflutterReportScreen(onClose: ...): report widget with optional close callback.
Trigger Behavior #

- Floating trigger is draggable (
onPanUpdate) so you can move it away from important UI. - Floating trigger uses opacity (
0.5) so it does not heavily hide content. - Trigger mode can be changed from report
Settingsat runtime. - Report opens as an overlay screen on top of current app content.
Production Note #
Disable Perflutter in production builds.
Recommended pattern:
import 'package:flutter/foundation.dart';
import 'package:perflutter/perflutter.dart';
MaterialApp(
navigatorObservers: kDebugMode ? [PerflutterNavigatorObserver()] : const [],
builder: (context, child) {
return PerflutterTrigger(
enabled: kDebugMode,
triggerMode: PerflutterTriggerMode.floatingButton,
child: child ?? const SizedBox.shrink(),
);
},
);
This keeps performance instrumentation for development/testing only.
Report Screen Overview #

The report contains:
- Session Overview
- Sort + Collect controls
- Per-screen cards
- Device System Info
- Journey Breadcrumb
On every open, the first screen card is expanded by default for quick inspection.
Session Overview Numbers #

Session Time: how long the current tracking session has been running.Total Screen Visits: how many screen visits were tracked in this session.Total Frames: all rendered frames captured during the session.Dropped Frames: frames that missed smooth rendering targets.Frames Health %: overall smoothness score for the session.FPS (avg): average rendered frames per second for the session.Max Memory: highest memory usage observed in the session.
Per-Screen Card Numbers #
Each screen card shows:
- screen name
- duration for that visit (or aggregated duration in collect mode)
- estimated FPS
- frame health
- total frames
- dropped frames
- peak memory
- total visits (
xN) only when collect mode is enabled
Color Meaning #
Performance color (by drop rate):
- green:
< 5% - orange:
5%to< 15% - red:
>= 15%
Memory color (by MB):
- green:
< 350 - orange:
350to< 600 - red:
>= 600
Sort And Collect #
Sort:
Latest: newest entries firstLow Perf: highest dropped-frame ratio first
Collect button:
Collect(off): show each visit separatelyCollected(on): merge same screen names into one aggregated card- in collected mode, visits are merged and
Total Visitsis shown - collect toggle state is kept during the current app session

Journey Breadcrumb #
Journey section shows navigation order for the session, like:
Home > HeavyScreen > NormalScreen
Use it to correlate performance issues with the user path that led to them.
Device System Info #
Shows current device descriptor:
- Android:
manufacturer + model + Android version - iOS:
device name + system name + system version
This helps you compare performance behavior by device class and OS version.
All Buttons Explained #
Trigger FAB: open reportClose (X): close report and return to appRefresh: reset tracking session dataSettings: switch trigger mode (Floating Button/Long Press)Sort chips: change orderingCollect chip: toggle per-visit vs per-screen aggregation
Example App In This Repository #
The demo app (example/lib/main.dart) includes:
| Normal Screen: Moderate rendering workload. |
Heavy Screen: Raster-heavy animated layers with stress levels. |
|---|---|
![]() |
![]() |
Use them to validate that metrics react clearly to lighter vs heavier rendering pressure.

