diff --git a/README.md b/README.md index e331656..39ed369 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ An APM library for detecting UI jank in Flutter for mobile (Android/iOS). Building smooth APPs with Flutter is easy, but as your APP grows in complexity and faces a variety of user environments and devices, ensuring smooth performance in production can be challenging. Even if your app runs smoothly locally, it doesn't guarantee the same for all users. `glance` helps collect stack traces during UI jank, allowing you to pinpoint the exact function causing the performance issue, so you can resolve it effectively. -`glance` detects UI jank during the build phase as well as through various callbacks, such as, `WidgetBindingObserver` callbacks, touch events, and method channel callbacks. These cover most cases that cause UI jank. It works only in release or profile builds when your application is built with the [`--split-debug-info` option](https://docs.flutter.dev/deployment/obfuscate#obfuscate-your-app). +`glance` detects UI jank during the rendering phase as well as through various callbacks, such as, `WidgetBindingObserver` callbacks, touch events, and method channel callbacks. These cover most cases that cause UI jank. It works only in release or profile builds when your application is built with the [`--split-debug-info` option](https://docs.flutter.dev/deployment/obfuscate#obfuscate-your-app). ## Getting Started diff --git a/lib/src/glance.dart b/lib/src/glance.dart index d210c42..01f2702 100644 --- a/lib/src/glance.dart +++ b/lib/src/glance.dart @@ -6,7 +6,7 @@ import 'package:glance/src/glance_impl.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; /// A custom binding that connects [WidgetsFlutterBinding] and [Glance] to detect -/// UI jank during the build phase and from "external sources" such as callbacks from +/// UI jank during the rendering phase and from "external sources" such as callbacks from /// [WidgetsBindingObserver], touch events, and channel messages from the platform. class GlanceWidgetBinding extends WidgetsFlutterBinding with GlanceWidgetBindingMixin { @@ -88,6 +88,40 @@ class GlanceConfiguration { /// After obtaining the [JankReport.stackTrace], you can symbolize it using the `flutter symbolize` command. /// For more details, see https://docs.flutter.dev/deployment/obfuscate#read-an-obfuscated-stack-trace. /// You can save the stack traces to files or upload them to your server and symbolize them later. +/// +/// For example: +/// ```dart +/// // Implement your `JankDetectedReporter` +/// class MyJankDetectedReporter extends JankDetectedReporter { +/// @override +/// void report(JankReport info) { +/// final stackTrace = info.stackTrace.toString(); +/// // Save the stack traces to a file, or upload them to your server, +/// // symbolize them using the `flutter symbolize` command. +/// } +/// } +/// +/// void main() { +/// // Call `GlanceWidgetBinding.ensureInitialized()` first +/// GlanceWidgetBinding.ensureInitialized(); +/// // Start UI Jank Detection +/// Glance.instance.start(config: GlanceConfiguration(reporters: [MyJankDetectedReporter()])); +/// +/// runApp(const MyApp()); +/// } +/// ``` +/// +/// ## How it works +/// `glance` starts a dedicated [Isolate] internally to capture Dart UI thread stack traces using native stack unwinding. +/// Refer to [Sampler] for more details. +/// +/// To detect UI jank, `glance` extends [WidgetsFlutterBinding] and monitors execution time between [WidgetsFlutterBinding.handleBeginFrame] +/// and [WidgetsFlutterBinding.handleDrawFrame] during the rendering phase. It also tracks various callbacks such as [WidgetBindingObserver], +/// touch events, and method channel callbacks' invocations, checking each against its execution time. +/// Jank is detected when the execution time exceeds the [GlanceConfiguration.jankThreshold]. +/// +/// Upon detecting jank, `glance` fetches stack traces from the [Sampler] during the jank period and reconstructs them into Dart stack traces. +/// These are then reported to the [GlanceReporter], specified via [GlanceConfiguration.reporters]. abstract class Glance { Glance._(); diff --git a/lib/src/glance_impl.dart b/lib/src/glance_impl.dart index 3633e4e..cdf2281 100644 --- a/lib/src/glance_impl.dart +++ b/lib/src/glance_impl.dart @@ -289,7 +289,7 @@ typedef HandleDrawFrameEndCallback = void Function( typedef CheckJankCallback = void Function(int start, int end); -/// Besides the build phase check ([handleBeginFrame] to [handleDrawFrame]), we only +/// Besides the rendering phase check ([handleBeginFrame] to [handleDrawFrame]), we only /// override the functions that handle callbacks from the [PlatformDispatcher]. /// Other callbacks are handled by the channel called ([_DefaultBinaryMessengerProxy]). mixin GlanceWidgetBindingMixin on WidgetsFlutterBinding { @@ -307,8 +307,8 @@ mixin GlanceWidgetBindingMixin on WidgetsFlutterBinding { T traceFunctionCall(T Function() func) { int start = Timeline.now; final ret = func(); - // Only check jank if not in build phase, because if it is in buid phase, - // the jank has been checked by the build phase jank check + // Only check jank if not in rendering phase, because if it is in rendering phase, + // the jank has been checked by the rendering phase jank check if (schedulerPhase == SchedulerPhase.idle) { _onCheckJank?.call(start, Timeline.now); }