I've been struggling with severe janks with the "official" flutter video_player package in combination with the PageView widget.
My Goal
Scroll smoothly and quickly through several pages of a PageView widget, that contain a Video widget each.
Actual Result
When I try to scroll through those pages quickly, I get terrible janks/performance issues. When I swipe through the pages slowly, and wait for the scrolling animation to finish, everything is smooth. See my video recorded on a Xiaomi Redmi Note 8 Pro in profile mode as proof.
GIF: video proof of the janks in the app
Performance Analysis
I tried finding help by consulting flutter performance tool. The tool shows massive spikes in raster time. In one example 51.7 ms raster time, 43.0 ms of that time needed for shader compilation. I'm not experienced enough to understand what that means or how that information helps me, though. Screenshot follows:
screenshot: flutter performance tool screenshot showing slow frame
What I tried so far
- Removing the line
controller.dispose();
resolves the issue, but that leeds to memory leaks and the widgets crashing eventually. - I tried wrapping the
controller.dispose();
into aWidgetsBinding.instance!.addPostFrameCallback((_) async {}
, but that didn't help
My Code
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class ExamplePageView extends StatelessWidget {
ExamplePageView({Key? key}) : super(key: key);
final PageController pageController = PageController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
child: PageView(
controller: pageController,
onPageChanged: (value) {},
children: [
ExampleVideo(),
ExampleVideo(),
ExampleVideo(),
ExampleVideo(),
ExampleVideo(),
ExampleVideo(),
],
),
),
);
}
}
class ExampleVideo extends StatefulWidget {
const ExampleVideo({Key? key}) : super(key: key);
@override
State<ExampleVideo> createState() => _ExampleVideoState();
}
class _ExampleVideoState extends State<ExampleVideo> {
late VideoPlayerController controller;
@override
void initState() {
super.initState();
controller = VideoPlayerController.network(
"https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4");
controller
..initialize()
..addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height,
),
child: AspectRatio(
aspectRatio: 16 / 9,
child: controller.value.isInitialized
? VideoPlayer(controller)
: Container(
color: Colors.black,
),
),
),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
Flutter Doctor shows no issues, video_player and flutter are in their respective latest version. Thank you for helping! :)
Also posted on flutter's github