Flutter笔记:关于SchedulerBinding
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSite:http://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/139018015
HuaWei:https://bbs.huaweicloud.com/blogs/427627
【简介】:在Flutter开发中WidgetsFlutterBinding更常见,一般不会直接使用SchedulerBinding。实际上WidgetsFlutterBinding、RenderdingFlutterBinding组合了SchedulerBinding等更多底层的Bing。本文基于Flutter源码及其相关注释,记录关于SchedulerBinding相关内容。比较而言,WidgetsBinding主要关注应用的上层逻辑和状态,而SchedulerBinding主要关注底层的任务调度和执行。
在Flutter框架中,SchedulerBinding
是一个非常重要的mixin
,它为Flutter应用程序提供了调度帧(Frame)和任务(Task)的核心功能。SchedulerBinding
与Flutter引擎紧密配合,负责管理帧的生命周期,协调各种类型的回调函数,以及优化应用的性能。
SchedulerBinding是Flutter框架中不可或缺的一部分,它为开发者提供了控制应用生命周期、优化性能的强大工具。SchedulerBinding在Flutter框架中的的功能包括:
- 它是连接Flutter应用程序和Flutter引擎的桥梁,负责与引擎进行通信,接收引擎发出的帧事件(Frame events),并触发相应的回调函数。
- 它管理着Flutter应用的帧率(Frame rate),根据设备性能和应用需求,自动调整帧率以提供流畅的用户体验。
- 它提供了注册和调度各种类型回调函数的API,包括Transient frame callbacks、Persistent frame callbacks和Post-frame callbacks等,让开发者能够在适当的时机执行自己的逻辑。
- 它还负责管理任务队列,根据任务的优先级和当前的调度策略,合理地安排任务的执行顺序,避免应用出现卡顿或无响应的情况。
SchedulerBinding的主要职责可以归纳为以下几点:
- 帧调度(Frame scheduling):与Flutter引擎协作,接收并处理
onBeginFrame
和onDrawFrame
回调,触发帧的构建(build
)和绘制(draw
)过程。 - 回调管理(Callback management):提供注册和移除Transient frame callbacks、Persistent frame callbacks和Post-frame callbacks的方法,确保回调函数在正确的时机被调用。
- 任务调度(Task scheduling):管理一个优先级队列,根据任务的优先级和当前的调度策略(
schedulingStrategy
),合理安排任务的执行顺序。 - 帧率控制(Frame rate control):根据设备性能和应用需求,动态调整帧率(timeDilation),以平衡流畅度和电池消耗。
- 生命周期管理(Lifecycle management):监听应用的生命周期事件(AppLifecycleState),如应用进入前台或后台,并触发相应的回调函数。
- 时间戳处理(Timestamp handling):提供
currentFrameTimeStamp
和currentSystemFrameTimeStamp
属性,供开发者获取当前帧的时间戳,同时还支持添加自定义的时间戳回调(TimestampCallback)。
通过对这些职责的有效履行,SchedulerBinding确保了Flutter应用能够高效、流畅地运行,并为开发者提供了灵活的控制手段。在后续的章节中,我们将深入探讨SchedulerBinding的关键概念和使用方法。
需要指出,SchedulerBinding是一种非常低层次、高风险的操作,只应该在一些非常特殊和罕见的场景下使用。在绝大多数情况下,我们都应该使用Flutter提供的高层API、组件和插件,以保证应用的性能、稳定性和可维护性。只有在我们确实需要实现一些Flutter框架不支持的、非常定制化的功能时,才应该考虑直接使用SchedulerBinding,并且要非常谨慎地进行设计、实现和测试。
要理解SchedulerBinding的工作原理和使用方法,首先需要了解一些关键概念。本节将介绍Frame、Frame callbacks以及SchedulerBinding中的几种callback
类型和调度阶段。
在Flutter中,Frame表示一次完整的UI渲染过程,包括构建Widget树、布局、绘制等步骤。Frame的生成由Flutter引擎驱动,通常以每秒60次的频率进行。
而Frame callbacks则是在每一帧的特定时间点被调用的回调函数。通过Frame callbacks,我们可以在一帧的不同阶段执行自定义的逻辑,例如启动动画、更新状态等。SchedulerBinding提供了注册和管理Frame callbacks的方法。
Transient frame callbacks是一次性的帧回调,只在注册后的下一帧被调用一次。可以通过SchedulerBinding.scheduleFrameCallback
方法注册Transient frame callback:
SchedulerBinding.instance.scheduleFrameCallback((_) {
// 在下一帧执行一些操作
print('Transient frame callback executed');
});
Transient callbacks适用于只需要执行一次的场景,例如触发一个动画。
与Transient frame callbacks不同,Persistent frame callbacks会在每一帧都被调用,直到被移除为止。可以通过SchedulerBinding.addPersistentFrameCallback
方法注册:
void onFrame(Duration timeStamp) {
// 在每一帧执行一些操作
print('Persistent frame callback executed');
}
SchedulerBinding.instance.addPersistentFrameCallback(onFrame);
要移除一个Persistent frame callback,可以调用SchedulerBinding.removePersistentFrameCallback
方法:
SchedulerBinding.instance.removePersistentFrameCallback(onFrame);
Persistent callbacks通常用于需要在每一帧都执行的场景,例如实时更新UI、动画等。
Post-frame callbacks会在当前帧的所有Persistent callbacks执行完毕后、下一帧开始前被调用。可以通过SchedulerBinding.addPostFrameCallback
方法注册:
SchedulerBinding.instance.addPostFrameCallback((_) {
// 在当前帧结束后执行一些操作
print('Post-frame callback executed');
});
Post-frame callbacks适用于需要在当前帧的最后执行的场景,例如在布局或绘制完成后更新状态。
SchedulerBinding将一帧划分为几个阶段,不同类型的callbacks
在不同阶段执行:
- Idle(空闲): 表示当前没有正在处理的帧。
- Transient callbacks(瞬时回调): 执行Transient frame callbacks。
- Midframe microtasks(帧中微任务): 执行Transient callbacks产生的微任务。
- Persistent callbacks(持久回调): 执行Persistent frame callbacks。
- Post-frame callbacks(后帧回调): 执行Post-frame callbacks。
了解这些阶段有助于了解这些阶段有助于我们选择合适的callback
类型,并避免在错误的阶段执行耗时操作而影响UI性能。例如,在Persistent callbacks
阶段执行复杂的计算或I/O操作可能会导致掉帧。
通过SchedulerBinding.schedulerPhase
属性可以获取当前的调度阶段:
SchedulerPhase phase = SchedulerBinding.instance.schedulerPhase;
if (phase == SchedulerPhase.persistentCallbacks) {
// 在持久回调阶段执行一些操作
} else if (phase == SchedulerPhase.idle) {
// 在空闲阶段执行一些操作
}
理解Frame、Frame callbacks以及SchedulerBinding的调度阶段,是高效使用SchedulerBinding
的基础。在实际应用中,我们应该根据具体的需求选择合适的callback
类型和调用时机,避免不必要的性能开销,从而构建流畅、响应迅速的Flutter应用。
Transient frame callbacks 是一次性的帧回调,会在下一帧开始时被调用,调用后就会自动移除。我们可以通过 SchedulerBinding.instance.scheduleFrameCallback
方法来注册一个 Transient frame callback:
int id = SchedulerBinding.instance.scheduleFrameCallback((_) {
// 在下一帧开始时执行一些操作
...
}, rescheduling: false);
其中 rescheduling
参数表示是否在回调执行完后自动重新注册,一般不需要。
如果要提前移除一个 Transient frame callback,可以使用 SchedulerBinding.instance.cancelFrameCallbackWithId
方法:
SchedulerBinding.instance.cancelFrameCallbackWithId(id);
Persistent frame callbacks 是持久的帧回调,一旦注册后,每一帧都会被调用,直到主动移除。我们可以通过 SchedulerBinding.instance.addPersistentFrameCallback
方法来注册:
void callback(Duration timeStamp) {
// 在每一帧执行一些操作
...
}
SchedulerBinding.instance.addPersistentFrameCallback(callback);
如果要移除一个 Persistent frame callback,可以使用 SchedulerBinding.instance.removePersistentFrameCallback
方法:
SchedulerBinding.instance.removePersistentFrameCallback(callback);
Post-frame callbacks 是一次性的后帧回调,会在当前帧绘制完成后被调用。我们可以通过 SchedulerBinding.instance.addPostFrameCallback
方法来注册:
SchedulerBinding.instance.addPostFrameCallback((_) {
// 在当前帧绘制完成后执行一些操作
...
});
Post-frame callbacks 不需要主动移除,在回调函数执行完后会自动移除。
除了帧回调,SchedulerBinding 还提供了调度和执行任务的能力。我们可以通过 SchedulerBinding.instance.scheduleTask
方法来调度一个异步任务:
SchedulerBinding.instance.scheduleTask(() async {
// 执行一些异步任务
...
}, Priority.animation);
其中第二个参数是任务的优先级,优先级越高的任务会越早执行。
SchedulerBinding 内部有一个任务队列,任务会在每一帧的空闲时间去执行。如果某一帧有动画回调,则优先级低于 Priority.animation
的任务会暂停执行,让出时间给动画,避免动画卡顿。
以上就是 SchedulerBinding 的一些主要功能和用法,它为 Flutter 应用提供了灵活的调度能力。合理利用 SchedulerBinding,可以实现各种自定义的动画效果、与外部数据源同步、优化性能等功能,是 Flutter 开发中非常重要的一个类。
Flutter默认的帧率是60fps,但有时我们可能需要降低帧率以节省电量,或者提高帧率以获得更流畅的动画效果。SchedulerBinding提供了timeDilation
属性来控制帧率:
// 降低帧率到30fps
SchedulerBinding.instance.timeDilation = 2.0;
// 提高帧率到120fps
SchedulerBinding.instance.timeDilation = 0.5;
timeDilation
的默认值为1.0,表示60fps。设置为2.0时,每一帧的时间会变为原来的2倍,所以帧率降为30fps。设置为0.5时,每一帧的时间会变为原来的一半,所以帧率提高为120fps
。
注意,提高帧率会增加CPU和GPU的负载,可能会导致耗电增加和发热加剧,所以一般只在必要时短暂地提高帧
SchedulerBinding提供了一些属性和方法来监听应用的生命周期事件:
lifecycleState
属性:表示应用当前的生命周期状态,是一个AppLifecycleState枚举值。addObserver
和removeObserver
方法:可以添加和移除SchedulerObserver
,在应用生命周期状态发生变化时会收到通知。
例如:
class MySchedulerObserver implements SchedulerObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
print('App lifecycle state changed to $state');
}
}
MySchedulerObserver observer = MySchedulerObserver();
SchedulerBinding.instance.addObserver(observer);
上面的代码添加了一个SchedulerObserver
,它会在应用生命周期状态发生变化时打印出新的状态。
SchedulerBinding
允许我们添加时间戳回调函数,在每一帧开始时,Flutter引擎会将该帧的时间戳信息传递给这些回调函数。这对于实现一些需要精确计时的功能非常有用,比如音视频同步、数据采集等。
可以通过SchedulerBinding.instance.addTimingsCallback
方法添加时间戳回调:
void callback(List<FrameTiming> timings) {
// 处理时间戳信息
...
}
SchedulerBinding.instance.addTimingsCallback(callback);
- 点赞
- 收藏
- 关注作者
评论(0)