我想在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)),
],
),
);}
);
}
答案 0 :(得分:2)
您不应在build方法中创建视频播放器控制器。您想在build方法之外创建控制器,以便在滚动时不会一直被重新创建。
答案 1 :(得分:0)
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(() {});
});
@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(),);
}
},
);
}
}
答案 2 :(得分:0)
请阅读有关Butter player的信息。
我认为这适用于应用中视频播放器的许多可能应用。
答案 3 :(得分:0)
一次只播放一个视频。要获取 currentIndex 使用 CarouselSlider。您将在 onPageChanged 参数中获得索引。
Container(
key: new PageStorageKey(
"keydata$index",
),
child: VideoWidget(
play: index==currentIndex?true:false, //changed
url: itemList.elementAt(index),
)
),