【问题标题】:SliverAppBar: How to keep native view alive during scrolling?SliverAppBar:如何在滚动过程中保持原生视图处于活动状态?
【发布时间】:2019-01-21 10:07:02
【问题描述】:

我想在 SliverAppBar 的 flexibleSpace 中显示一个原生视图 (HeaderContainer) 并阻止它重建。

return new Scaffold(
    body: CustomScrollView(
        slivers: <Widget>[
            SliverAppBar(
                backgroundColor: Colors.teal,
                pinned: true,
                expandedHeight: 180,
                flexibleSpace: FlexibleSpaceBar(
                    background: HeaderContainer(),
                    // HeaderContainer is a native View (AndroidView)
                ),
             ),
             SliverList(
                delegate: SliverChildListDelegate([content]),
            )
        ]
    )
);

不幸的是 HeaderContainer() 在滚动过程中变得不可见时被破坏了。
HeaderContainer() 的创建非常昂贵并且需要一些时间。

是否有可能将此小部件保存在内存中并防止它在滚动时被破坏?

更新:

回滚后重建 HeaderContaienr 的问题只是原生视图(例如 AndroidView)的问题。


一些调查:

FlexibleSpaceBar 使用此行添加子项:

@override
Widget build(BuildContext context) {
    ...
    if (opacity > 0.0) {    <-- !
        children.add( ... );
    }

因此,如果不透明度大于零,则仅将子级添加到树中,如果不透明度为零,则将其删除(并销毁)。这会导致回滚后重建。

我最终得到了一个自定义的 flexibleSpace 小部件,其中孩子总是被添加到视图树中。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    只要您setState,您的小部件树就会重建以匹配任何更改。每次滚动时,都需要渲染一个新帧,因此您抱怨的性能。您想到了 3 个选项:

    1.您可能希望在您的HeaderContainer 上使用const 构造函数

    2.您可以尝试将您的HeaderContainer 分配为最终变量 你的 build 方法,所以它只会重建依赖关系 如果当前小部件实例保持不变,则更改,例如:

    @override
    Widget build(BuildContext context) {
      final header = HeaderContainer();
    
      return new Scaffold(
        body: CustomScrollView(
            slivers: <Widget>[
                SliverAppBar(
                    backgroundColor: Colors.teal,
                    pinned: true,
                    expandedHeight: 180,
                    flexibleSpace: FlexibleSpaceBar(
                        background: header,
                    ),
                 ),
                       SliverList(
                       delegate: SliverChildListDelegate([content]),
                   )
               ]
           )
      );
    

    3.或者您可以将此header 添加为有状态小部件的属性 但请记住,这会破坏该小部件的热重载 (标题)。

    【讨论】:

    • 您需要将final header = HeaderContainer(); 移出build() 才能按照您的描述工作。在您的示例中,每次调用 build() 时都会创建一个新的 HeaderContainer()
    • 那是选项 3。在选项 2 中,它位于 build 方法中,你是对的,它只会在你 setState 甚至重建父小部件时重建,但实际上不会,如果你'在树的一些小部件中使用流,只是为了澄清。
    • 这一切都适用于颤振小部件,但对原生视图没有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 2022-06-28
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    相关资源
    最近更新 更多