Using the GetX state management, develope a social media app like TikTok, where user can watch videos. When scroll vertically, video get changed. So I have implement the same functionality in my code. I have used VideoPlayer(video_player) package.From the api it fetch multiple videos. In my code, I have initialized all the video controller from the list, and play the video. But I want that, when the app is started, initialized 0 index video and play it from the list, at that time 1 index video was initialized. When the user change to the next video (0 index -> 1 index) then 1 index video was started playing, 0 index video was paused and 2 index video is get initialized. Again the video change to next video, then 2 index video was started playing, 1 index video was stopped & 0 index video get disposed also 3 index video was initialized. Logic was implemented for forward scrolling. When the user reverse scrolling, logic was viceversa. Basically i need the preloading videos.
Here the above screenshot,i attach the logic of the preloading videos.
Here is my code :
class HomeScreenNew extends StatefulWidget {
const HomeScreenNew({super.key});
@override
State<HomeScreenNew> createState() => _HomeScreenNewState();
}
class _HomeScreenNewState extends State<HomeScreenNew> {
late PageController pageController;
late ScrollController scrollController;
final List<VideoPlayerController> controllers = [];
final List<ValueNotifier<double>> _progressIndicators = [];
final VideoControllerX controllerX = Get.put(VideoControllerX());
@override
void initState() {
super.initState();
pageController = PageController(initialPage: 0);
scrollController = ScrollController();
controllerX.fetchHomeVideos().then((_) {
for (var video in controllerX.videoList) {
VideoPlayerController controller =
VideoPlayerController.networkUrl(Uri.parse(video.videoUrl))
..initialize().then((value) {
setState(() {});
});
controllers.add(controller);
_progressIndicators.add(ValueNotifier<double>(0.0));
controller.addListener(() {
_updateProgress(controller);
});
}
// Initialize and play the first video
_playCurrentVideo(0);
//----- Add a listener to detect when the page scrolling state changes
pageController.addListener(() {
if (pageController.page != null &&
pageController.page!.round() == pageController.page) {
// Page has settled, play the current video and pause the others
_playCurrentVideo(pageController.page!.toInt());
}
});
});
}
@override
void dispose() {
for (var controller in controllers) {
controller.removeListener(() {});
controller.dispose();
}
for (var progressIndicator in _progressIndicators) {
progressIndicator.dispose();
}
pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: controllers.length,
scrollDirection: Axis.vertical,
pageSnapping: true,
onPageChanged: (value) {
_playCurrentVideo(value);
},
itemBuilder: (context, index) {
final newController = controllers[index];
newController
..play()
..setLooping(true);
return newController.value.isInitialized
? Stack(
fit: StackFit.expand,
children: [
//-------------Main Video Screen--------
AspectRatio(
aspectRatio: newController.value.aspectRatio,
child: VideoPlayer(newController),
),
//--------Video Progress Bar-------
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: ValueListenableBuilder(
valueListenable: _progressIndicators[index],
builder: (context, value, child) {
return LinearProgressIndicator(
value: value,
backgroundColor: Colors.white,
valueColor:
const AlwaysStoppedAnimation(Colors.red),
);
},
))
],
)
: Container(
color: Colors.black,
child: const Center(
child: CircularProgressIndicator(),
),
);
},
),
);
}
//-----Play the current video and pause the others-----
void _playCurrentVideo(int index) {
for (var i = 0; i < controllers.length; i++) {
if (i == index) {
controllers[i].play();
} else {
controllers[i].pause();
controllers[i].seekTo(const Duration(milliseconds: 0));
}
}
}
//---------Update Progress----------
void _updateProgress(VideoPlayerController controller) {
int controllerIndex = controllers.indexOf(controller);
if (controllerIndex == -1) {
return;
}
final progress = controller.value.position.inMilliseconds /
controller.value.duration.inMilliseconds;
_progressIndicators[controllerIndex].value = progress;
}
}
I want to display the videos, like tiktok reels or instagram reels, where video fetch seamless without any load. I am trying to manage the videocontroller initialize and dispose index wise which i have mention above. But in my code, all videocontroller was initialized at a time .So I think it might get load in the app. Anyone have any solution that, how to handle preloading videos like controller the video controller in flutter app like Tiktok & Instagram reels.