我正在扑朔迷离地构建一个应用程序,其中包含一个像TikTok中找到的那样的Video Feed。您可以想象一个ListView,您可以在其中滚动浏览一些视频(5-25秒)。
视频存储在Google Cloud Platform中。
目前,可以理解的是,包含12个甚至9个以上(在某些内存较低的设备上)的feed导致该应用崩溃。
现在,我还是一个业余爱好者(几乎没有将GCP连接到Flutter,然后将其连接到:p),我正在努力寻找一种解决方案,以便能够尽可能平滑地滚动视频源。我当时在想带有可见性检测器的旋转木马,但不确定如何重新加载已处置的视频。 我的视频播放器是“ Video_player”软件包。
我乐于助人,感谢您的帮助!
谢谢, M
答案 0 :(得分:4)
您可以在下面复制粘贴运行完整代码
您可以使用软件包https://pub.dev/packages/inview_notifier_list
当视频在指定区域中显示在屏幕上时,示例代码将自动播放视频
代码段
InViewNotifierList(
scrollDirection: Axis.vertical,
initialInViewIds: ['0'],
isInViewPortCondition:
(double deltaTop, double deltaBottom, double viewPortDimension) {
return deltaTop < (0.5 * viewPortDimension) &&
deltaBottom > (0.5 * viewPortDimension);
},
children: List.generate(
30,
(index) {
return Container(
width: double.infinity,
height: 300.0,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(vertical: 50.0),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final InViewState inViewState =
InViewNotifierList.of(context);
inViewState.addContext(context: context, id: '$index');
return AnimatedBuilder(
animation: inViewState,
builder: (BuildContext context, Widget child) {
return VideoWidget(
play: inViewState.inView('$index'),
url:
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4');
},
工作演示
完整代码
import 'package:flutter/material.dart';
import 'package:inview_notifier_list/inview_notifier_list.dart';
import 'package:video_player/video_player.dart';
class VideoWidget extends StatefulWidget {
final String url;
final bool play;
const VideoWidget({Key key, @required this.url, @required this.play})
: super(key: key);
@override
_VideoWidgetState createState() => _VideoWidgetState();
}
class _VideoWidgetState extends State<VideoWidget> {
VideoPlayerController _controller;
Future<void> _initializeVideoPlayerFuture;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(widget.url);
_initializeVideoPlayerFuture = _controller.initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
if (widget.play) {
_controller.play();
_controller.setLooping(true);
}
}
@override
void didUpdateWidget(VideoWidget oldWidget) {
if (oldWidget.play != widget.play) {
if (widget.play) {
_controller.play();
_controller.setLooping(true);
} else {
_controller.pause();
}
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return VideoPlayer(_controller);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}
class VideoList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
InViewNotifierList(
scrollDirection: Axis.vertical,
initialInViewIds: ['0'],
isInViewPortCondition:
(double deltaTop, double deltaBottom, double viewPortDimension) {
return deltaTop < (0.5 * viewPortDimension) &&
deltaBottom > (0.5 * viewPortDimension);
},
children: List.generate(
30,
(index) {
return Container(
width: double.infinity,
height: 300.0,
alignment: Alignment.center,
margin: EdgeInsets.symmetric(vertical: 50.0),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final InViewState inViewState =
InViewNotifierList.of(context);
inViewState.addContext(context: context, id: '$index');
return AnimatedBuilder(
animation: inViewState,
builder: (BuildContext context, Widget child) {
return VideoWidget(
play: inViewState.inView('$index'),
url:
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4');
},
);
},
),
);
},
),
),
Align(
alignment: Alignment.center,
child: Container(
height: 1.0,
color: Colors.redAccent,
),
)
],
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: VideoList()),
],
),
),
);
}
}