本篇内容主要讲解“Flutter MultiFrameImageStreamCompleter是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Flutter MultiFrameImageStreamCompleter是什么”吧!MultiFrameImageStreamCompleter
是一个可组合的 ImageStreamCompleter
类,用于将多个 ImageStreamCompleter
对象合并为一个单独的 ImageStream
对象,通常用于动画效果。每当子 ImageStreamCompleter
接收到一个新的 ImageInfo
对象,它会立即通知其所有的监听器,并将对象传递给它们。当 MultiFrameImageStreamCompleter
的 addListener()
方法被调用时,它将传入的 ImageStreamListener
添加到其内部的子 ImageStreamCompleter
的监听器列表中。如果 MultiFrameImageStreamCompleter
本身接收到一个 ImageInfo
对象,它会将它传递给其所有的监听器。但是,它不会自己管理这些帧,而是委托给每个子 ImageStreamCompleter
来完成。MultiFrameImageStreamCompleter
还支持渐进式 JPEG,并实现了 addListener()
、removeListener()
和 dispose(免费云主机域名)
方法,以及一个名为 getNextFrame()
的方法,用于从图像流中获取下一帧。当所有帧都加载完毕后,MultiFrameImageStreamCompleter
将使用 dart:ui.Codec
解码器将它们合并为一个单独的 dart:ui.Image
对象,并将其传递给 setImage()
方法。最后,它将通知所有监听器,并将它们传递给 ImageStreamListener.onImage()
回调函数,以通知它们新的 ImageInfo
已经可用。当 MultiFrameImageStreamCompleter
的 dispose()
方法被调用时,它会将其所有子 ImageStreamCompleter
的 dispose()
方法依次调用,以释放所有资源,并取消所有未处理的帧请求。同时,它还会确保在释放资源之前将所有错误通知给其监听器。在_handleCodecReady
方法中,首先将传入的codec
对象赋值给成员变量_codec
,然后使用assert
语句来确保该变量不为空。接着,如果当前对象有监听器,则调用_decodeNextFrameAndSchedule
方法来解码下一帧并将其调度执行。这里的目的是为了尽早地开始解码下一帧图像,以尽快展示出完整的动画效果。如果没有监听器,则不需要解码下一帧图像,因为没有地方可以展示它。这个方法的作用是获取下一帧并在获取成功后调度下一帧的解码,如果帧数为1,即这是一个静态图片,则只需返回该帧,并在没有监听器时直接返回,如果帧数大于1,则调度下一帧的解码。在获取下一帧之前,方法会清除上一帧并将_nextFrame置为null,以便准备下一帧。如果解码下一帧时发生异常,则会记录错误并返回。如果在等待下一帧的解码期间移除了监听器,则在没有活动的监听器时不会发出帧,否则会发出帧并调度下一帧的解码。_emitFrame
方法的作用是向 ImageStreamCompleter
发送新的 ImageInfo
。具体实现是通过调用 setImage
方法将 ImageInfo
设置为 ImageStreamCompleter
的当前值,同时更新 _framesEmitted
计数器。getNextFrame()
是 Codec
类的一个方法,用于获取解码后的帧。具体来说,它会在 Codec
内部解码图像帧,返回一个 FrameInfo
对象,其中包含了解码后的 Image
对象以及该帧的时间戳和持续时间等信息。由于 Codec
可能会支持动画图像,因此 getNextFrame()
方法可能会返回多个帧。在 MultiFrameImageStreamCompleter
中,_decodeNextFrameAndSchedule()
方法会调用 _codec.getNextFrame()
方法获取下一帧图像,然后将其保存在 _nextFrame
属性中。如果 _codec
的 frameCount
属性为 1,说明这是一个静态图像,直接使用 _emitFrame()
方法发布该帧图像;否则,调用 _scheduleAppFrame()
方法安排下一帧的发布。这个方法在 _decodeNextFrameAndSchedule
中被调用,用于处理已解码的下一帧图像。如果当前帧是非动画图像,它会直接调用 setImage
方法更新 ImageStreamCompleter
的值,如果是动画图像,它会计划下一帧的显示并等待下一帧的解码。函数 _scheduleAppFrame()
的作用是调度一个Flutter引擎帧回调,在回调中会调用 _handleAppFrame()
函数。具体来说,这个函数的实现包含以下步骤:1、检查 _frameCallbackScheduled
标志,如果为 true,则说明帧回调已经被调度过,直接返回。2、将 _frameCallbackScheduled
标志设置为 true,表示帧回调已经被调度。3、调用 SchedulerBinding.instance.scheduleFrameCallback()
函数,向Flutter引擎注册一个帧回调。回调函数为 _handleAppFrame()
。4、在 _handleAppFrame()
函数中,将会根据当前动画播放的帧率和帧数,计算下一帧应该在何时被显示,然后再次调用 _decodeNextFrameAndSchedule()
函数,以获取并显示下一帧图像。这样就完成了一次动画播放的循环。函数 _handleAppFrame
是 MultiFrameImageStreamCompleter 的核心函数,用于处理多帧图像的逻辑。下面是对该函数的详细解读:1、_frameCallbackScheduled = false;
将 _frameCallbackScheduled
设为 false,表示下一帧还没有调度。2、 if (!hasListeners) { return; }
如果没有监听器,则直接返回。3、 assert(_nextFrame != null);
断言 _nextFrame
不为空。4、 _isFirstFrame() || _hasFrameDurationPassed(timestamp)
如果是第一帧或者帧时间已经超过了 _frameDuration
,则进行以下操作:5、 _emitFrame(ImageInfo(image: _nextFrame!.image.clone(), scale: _scale, debugLabel: debugLabel));
发出 ImageInfo
事件,将 _nextFrame
的图像信息作为参数传入。6、 _shownTimestamp = timestamp;
更新 _shownTimestamp
为当前时间戳。7、 _frameDuration = _nextFrame!.duration;
更新 _frameDuration
为 _nextFrame
的帧间隔时间。8、 _nextFrame!.image.dispose(); _nextFrame = null;
释放 _nextFrame
的图像资源并将 _nextFrame
设为 null。9、 final int completedCycles = _framesEmitted ~/ _codec!.frameCount;
计算已经完成的循环次数。10、 _codec!.repetitionCount == -1 || completedCycles
如果循环次数为 -1(表示无限循环)或者已经完成的循环次数小于等于 _codec
的循环次数,则进行以下操作:11、 _decodeNextFrameAndSchedule();
解码下一帧并调度下一帧的绘制。12、 final Duration delay = _frameDuration! - (timestamp - _shownTimestamp);
计算下一帧需要延迟的时间。13、_timer = Timer(delay * timeDilation, () { _scheduleAppFrame(); });
使用计时器来实现下一帧的延迟绘制。延迟时间为 delay
乘以 timeDilation
(可以通过调用 timeDilation = x
来改变时间流逝的速度)。当计时器触发时,将调用 _scheduleAppFrame
来调度下一帧的绘制。这个方法是 ImageStreamCompleter
类的方法,用于向 ImageStreamCompleter
添加监听器。当第一个监听器被添加到 ImageStreamCompleter
上时,会检查 _codec
是否为 null,如果不为 null 并且有多帧图像或者当前图像为 null,则会调用 _decodeNextFrameAndSchedule()
方法开始解码下一帧图像并计划渲染。这样做是为了确保在第一个监听器被添加到 ImageStreamCompleter
上时就开始解码下一帧图像并在下一帧渲染完成后通知所有监听器。如果 _codec
为 null 或者当前图像为单帧图像,则不会调用 _decodeNextFrameAndSchedule()
方法。在这个方法中,调用了 super.addListener(listener)
将监听器添加到监听器列表中。removeListener
方法用于从 MultiFrameImageStreamCompleter
中移除给定的 ImageStreamListener
。当移除后,如果该对象不再有任何监听器,就会取消定时器 _timer
。具体来说,该方法会先调用父类的 removeListener
方法,将该监听器从监听器列表中移除。接着,如果此时 hasListeners
为 false
,说明没有任何监听器,就会取消 _timer
定时器,以便释放资源。_maybeDispose()
是一个用来释放资源的方法,当图片流不再被监听时调用。它首先调用父类的_maybeDispose()
方法,以处理父类中的一些释放资源的逻辑。然后它会检查_disposed
属性是否为true,如果是,则取消并置空_chunkSubscription
,这个对象是用来订阅图像数据块的流。这样做是为了释放相关的资源,以防止内存泄漏。到此,相信大家对“Flutter MultiFrameImageStreamCompleter是什么”有了更深的了解,不妨来实际操作一番吧!这里是百云主机网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
本篇内容介绍了“JetpackCompose按钮组件如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!按钮组件Button是用户和系统交互的重要组件之一,它…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。