【问题标题】:Statefull widget initState() not hit inside a ListView有状态小部件 initState() 未在 ListView 内命中
【发布时间】:2021-09-29 23:34:00
【问题描述】:

尝试将audioplayer 插件集成到 Listview 中,这是我的结构,

                                         ListView.builder(
                                            cacheExtent: 50.0,
                                            reverse: true,
                                            padding:
                                                const EdgeInsets.all(15),
                                            controller:
                                                _listScrollController,
                                            itemCount: Chats.length,
                                            itemBuilder: (ctx, i) {
                                              print(firebaseUID);
                                              if (Chats[i].data()['IsFile'] !=null && Chats[i].data()['IsFile'] &&
                                                  Chats[i].data()['FileType'] !=null && Chats[i].data()['FileType'] ==
                                                      'audio') {
                                                return AudioSentChat(i: i);
                                              
                                              } else
                                                return Container();
                                            },
                                          );

而音频发送聊天是一个像这样的无状态小部件,

                                       child: Container(
                                          padding: EdgeInsets.only(top: 15),
                                          height: 75,
                                          child: PlayerWidget(
                                              url: Chats[i]
                                                  .data()['FileUrl'],
                                              mode: PlayerMode
                                                  .MEDIA_PLAYER),
                                        ),

PlayerWidget 是一个有所有播放/暂停交互的 Statefull 小部件,这里是https://github.com/luanpotter/audioplayers/blob/master/packages/audioplayers/example/lib/player_widget.dart

现在的问题是,

  1. 当一个新的音频文件被录制并添加到列表视图(添加到 firebase)时,用户界面会更新,但是当你播放它时,所有文件都是重复的,我检查了数据,这是完美的而不是重复的。
  2. 现在,当屏幕滚动一点然后播放文件时,它可以完美运行,没有任何重复。

观察,player_widget 中的 intiState() 不会在 Listview 更新时触发。

如何处理,将有状态的小部件放在列表视图中也是一个坏主意。

【问题讨论】:

    标签: firebase flutter listview


    【解决方案1】:

    initState() 是一种在有状态小部件插入到小部件树时调用一次的方法,即它用于一次初始化,您可以做的是在更新列表视图时调用一个再次检索数据的函数

    例子

    OnTap: setState((){
      Function ();
    });
    
    

    【讨论】:

      【解决方案2】:

      您可以使用在didUpdateWidget 中添加_initAudioPlayer 方法。

      如果父小部件重建并请求该位置在 树更新以显示具有相同 runtimeType 的新小部件和 Widget.key,框架会更新这个的widget属性 状态对象引用新的小部件,然后调用此方法 上一个小部件作为参数。

      https://api.flutter.dev/flutter/widgets/State/didUpdateWidget.html

      因此,当父小部件重建时,您可以使用didUpdateWidget 再次运行_initAudioPlayer 方法,因为initState 在小部件的生命周期内只调用一次。

        @override
        void initState() {
          super.initState();
          _initAudioPlayer();
        }
      
        @override
        void didUpdateWidget(PlayerWidget oldWidget) {
          super.didUpdateWidget(oldWidget);
          _initAudioPlayer();
        }
      

      【讨论】:

      • didUpdateWidget 被击中,但不是新记录,所有旧记录,直到用户手动执行 Listview 延迟加载,新音频文件未绑定,即用户必须手动滚动,然后一切正常。计划以编程方式使用scrollContrller进行小滚动:(
      猜你喜欢
      • 1970-01-01
      • 2021-01-08
      • 2021-05-23
      • 2023-04-03
      • 2021-06-24
      • 2021-12-24
      • 2021-07-22
      • 2019-11-24
      • 1970-01-01
      相关资源
      最近更新 更多