【问题标题】:Flutter : Video player in ListView.builder (using : Chewie)Flutter:ListView.builder 中的视频播放器(使用:Chewie)
【发布时间】:2019-02-17 14:38:48
【问题描述】:

我很想在 ListView.builder 中创建一个视频播放器。我的视频存储在 Firestore 中。在 ListView.builder 中加载视频时没有问题,但是每当您向上和向下滚动页面时,我都会在红色框中收到错误消息:

一个 VideoPlayerController 在被释放后被使用。

I/flutter : 一旦你在 VideoPlayerController 上调用了 dispose(),它就不能再使用了。

Widget _modeApp(){
  return new ListView.builder(
      itemCount: dataApp.length,
      itemBuilder: (context,i){
        String _path = dataApp[i].url;
        _controllers.add(new TextEditingController());
        _focusNode.add(new FocusNode());
        return new Card(
          child: new Column(
              children: <Widget>[
                new Row(
                children: <Widget>[
                  new Container(
                    width: 50.0,
                    height: 50.0,
                    margin: const EdgeInsets.all(15.0),
                    decoration: new BoxDecoration(
                        border: new Border.all(color: Colors.black38),
                        shape: BoxShape.circle,
                        image: new DecorationImage(image: new NetworkImage(dataApp[i].aurl))
                    ),
                  ),
                  new Text(dataApp[i].name,style: new TextStyle(fontWeight: FontWeight.bold)),
                ],
              ),
                new Chewie(
                  VideoPlayerController.network(_path),
                    aspectRatio: 3 / 2,
                    autoPlay: false,
                    looping: false,
              ),
                new Container(
                margin: const EdgeInsets.only(left: 12.0,top: 12.0),
                child: new Row(
                  children: <Widget>[
                    new Icon(Icons.favorite_border,size: 27.0),
                    new Padding(padding: EdgeInsets.only(left: 15.0)),
                    new Icon(Icons.chat_bubble_outline,size: 27.0),
                    new Padding(padding: EdgeInsets.only(left: 15.0)),
                    new Icon(Icons.turned_in_not,size: 27.0),
                  ],
                ),
              ),
                new ListTile(
                title: new Text(dataApp[i].text,style: new TextStyle(fontWeight: FontWeight.bold),),
                subtitle:  new Text(dataApp[i].time),
              ),
                new ListTile(
                leading: new Container(
                  width: 50.0,
                  height: 50.0,
                  decoration: new BoxDecoration(
                    border: new Border.all(color: Colors.black38),
                    shape: BoxShape.circle,
                    image: widget.accountEmail == null
                        ? new DecorationImage(image: new NetworkImage("${widget.value.photoUrl}"))
                        : new DecorationImage(image: new NetworkImage("${widget.accountPhoto}")),
                  ),
                ),
                title: new EnsureVisibleWhenFocused(
                  focusNode: _focusNode[i],
                  child: new TextField(
                    focusNode: _focusNode[i],
                    controller: _controllers[i],
                    style: new TextStyle(
                        fontSize: 15.0,
                        color: Colors.black
                    ),
                    decoration: new InputDecoration(
                      border: InputBorder.none,
                      hintText: "Add a comment...",
                      hintStyle: new TextStyle(color: Colors.grey),
                    ),
                  ),
                ),
                trailing: new IconButton(
                    icon: new Icon(Icons.send, color: _controllers[i].text != "" ? Colors.blue : null), onPressed: _controllers[i].text != "" ? () => _showMessage(i) : null),
              ),
                new Padding(
                  padding: EdgeInsets.only(top: 13.0)),
            ],
          ),
        );}
      );
  }

【问题讨论】:

  • 您最终找到解决方案了吗?

标签: flutter


【解决方案1】:

您不应该在 build 方法中创建视频播放器控制器。您想在 build 方法之外创建控制器,这样它就不会在您滚动时不断重新创建。

【讨论】:

  • 但问题是如果我想在 listview.builder 中使用视频播放器,那么我该怎么做,因为我不知道哪个索引有视频,就像 instagram 一样,所以当我启动视频播放器时,链接必须提供,那我该怎么做呢?
【解决方案2】:
  1. 输入您的代码代替 Lisrview.builder()
 Container(
            child: 
              SingleChildScrollView(
                    physics: new BouncingScrollPhysics(),
                    scrollDirection: Axis.vertical,
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        ListView.separated(
                          shrinkWrap: true,
                          cacheExtent: 1000,
                          physics: NeverScrollableScrollPhysics(),
                          scrollDirection: Axis.vertical,
                          key: PageStorageKey(widget.position),
                          addAutomaticKeepAlives: true,
                          itemCount: itemList.isEmpty ? 0 : itemList.length,
                          itemBuilder: (BuildContext context, int index) =>
                              Container(
                            width: double.infinity,
                            height: 350.0,
                            alignment: Alignment.center,
    
                            child: Container(
                                key: new PageStorageKey(
                                  "keydata$index",
                                ),
    
                                child: VideoWidget(
                                    play: true,
    
                                    url: itemList.elementAt(index),
                                )
                            ),
                          ),
                          separatorBuilder: (context, index) {
                            return Divider();
                          },
                        ),
                      ],
                    ),
                  )
                 )
    
    class VideoWidget extends StatefulWidget {
    
      final bool play;
      final String url;
      
       const VideoWidget({Key key, @required this.url, @required this.play})
          : super(key: key);
          
            @override
      _VideoWidgetState createState() => _VideoWidgetState();
    }
    
    
    class _VideoWidgetState extends State<VideoWidget> {
      VideoPlayerController videoPlayerController ;
      Future<void> _initializeVideoPlayerFuture;
      
      @override
      void initState() {
        super.initState();
        videoPlayerController = new VideoPlayerController.network(widget.url);
    
        _initializeVideoPlayerFuture = videoPlayerController.initialize().then((_) {
    //       Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
          setState(() {});
        });
    } // This closing tag was missing
        
         @override
      void dispose() {
         videoPlayerController.dispose();
    //    widget.videoPlayerController.dispose();
        super.dispose();
      }
      
      
      @override
      Widget build(BuildContext context) {
      
      return FutureBuilder(
          future: _initializeVideoPlayerFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              return new Container(
    
                child: Card(
                key: new PageStorageKey(widget.url),
                  elevation: 5.0,
                  child: Column(
                    children: <Widget>[
                    Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Chewie(
                          key: new PageStorageKey(widget.url),
                          controller: ChewieController(
                            videoPlayerController: videoPlayerController,
                            aspectRatio: 3 / 2,
                            // Prepare the video to be played and display the first frame
                            autoInitialize: true,
                            looping: false,
                            autoPlay: false,
                            // Errors can occur for example when trying to play a video
                           // from a non-existent URL
                            errorBuilder: (context, errorMessage) {
                              return Center(
                                child: Text(
                                  errorMessage,
                                  style: TextStyle(color: Colors.white),
                                ),
                              );
                            },
                          ),
                        ),
                      ),  
                      ],
                  ),
                ),
              );
            }
            else {
              return Center(
                child: CircularProgressIndicator(),);
            }
          },
        );
      }
     }

【讨论】:

  • 我喜欢 VideoWidget 被抽象成一个类的方式。 :thumbup:
【解决方案3】:

请阅读Butter player

我认为这适用于应用中视频播放器的许多可能应用。

【讨论】:

    【解决方案4】:

    一次只能播放一个视频。要获取 currentIndex,请使用 CarouselSlider。您将在 onPageChanged 参数中获得索引。

                            Container(
                                key: new PageStorageKey(
                                  "keydata$index",
                                ),
    
                                child: VideoWidget(
                                    play: index==currentIndex?true:false, //changed
    
                                    url: itemList.elementAt(index),
                                )
                            ),
    

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 2020-06-04
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 2014-05-01
      • 2013-03-05
      相关资源
      最近更新 更多