0

I'm little bit confused because I was thinking there are no memory leak in flutter since there is no concept of weak (if I'm correct).
I'm running this on iOS device.
I'm trying to play videos and initialize some videos beforehand so that user can see it without delay.
To do that I prepared six VideoPlayerController and make those always being initialized while current video is playing.
There are three more initialized VideoPlayerController next to current one and two more initialized ones before current one like image below. With this logic I play video very smoothly back and forth. But after play about ten videos, app crush because of memory issue. I tried every function Future, async, await but still eats lots of memories. I'm not sure but it might be NotificationListener?
Since onNotification returns bool not Future or is this something to do with main thread or something?
Does anyone know how to fix this memory issue?

Code:

    class _SwiperScreenState extends State<SwiperScreen> {
      VideoPlayerController _firstController;
      VideoPlayerController _secondController;
      VideoPlayerController _thirdController;
      VideoPlayerController _fourthController;
      VideoPlayerController _fifthController;
      VideoPlayerController _sixthController;
      List<VideoPlayerController> _controllers;
      List<String> urls = [
        'https://firebasestorage.googleapis.com/v0/b/waitingboy-34497.appspot.com/o/video%2F8-21%2F1534825377992OsfJfKsdf90K8sf?alt=media&token=12245ee4-1598-4f7e-ba28-a9eb72ca474e',
        'http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4',
        'https://firebasestorage.googleapis.com/v0/b/waitingboy-34497.appspot.com/o/video%2F8-21%2F1534825377992OsfJfKsdf90K8sf?alt=media&token=12245ee4-1598-4f7e-ba28-a9eb72ca474e',
        'http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4',
      ];
      int currentIndex = 0; //refer to current playing controller index
      int videosIndex = 0; //refer to current playing urls index

      bool _didGetNotification(ScrollNotification notification) {
        if (notification is UserScrollNotification) {
          if (notification.direction.toString() == 'ScrollDirection.reverse') {
        //swipe to left so add one more video
            videosIndex++;
        //modify index so that always in the range of 0 ~ 5.
            if (currentIndex <= 2) {
              final int prepareIndex = currentIndex + 3;
              urls.add(
                  'https://firebasestorage.googleapis.com/v0/b/waitingboy-34497.appspot.com/o/video%2F8-21%2F1534825377992OsfJfKsdf90K8sf?alt=media&token=12245ee4-1598-4f7e-ba28-a9eb72ca474e');
              _initVideo(urls[videosIndex], prepareIndex);
            } else {
              final int prepareIndex = (currentIndex + 3) - 6;
              urls.add(
                  'http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4');
              _initVideo(urls[videosIndex], prepareIndex);
            }
          }
          if (notification.direction.toString() == 'ScrollDirection.forward') {
       //swipe to right so back one more video
            videosIndex--;
       //modify index so that always in the range of 0 ~ 5 .
            if (currentIndex >= 2) {
              final int videoIndex = videosIndex - 2;
              final int prepareIndex = currentIndex - 2;
              _initVideo(urls[videoIndex], prepareIndex);
            } else {
              final int videoIndex = videosIndex - 2;
              final int prepareIndex = 4 + currentIndex;
              _initVideo(urls[videoIndex], prepareIndex);
            }
          }
        }
        return true;
      }

      Future _initVideo(String url, int initIndex) async {
        if (_controllers[initIndex] != null) {
          await _controllers[initIndex].dispose();
        }

        _controllers[initIndex] = new VideoPlayerController.network(url);
        await _controllers[initIndex].initialize().then((_) async => await _controllers[initIndex].setLooping(true));
        setState(() {});
      }

      Future _initFirstThree() async {
         for  (int i = 1; i < urls.length; i++) {
          await _initVideo(urls[i], i);
        }
      }

      @override
      void initState() {
        _controllers = [
          _firstController,
          _secondController,
          _thirdController,
          _fourthController,
          _fifthController,
          _sixthController
        ];
        _initVideo(urls[0], 0).then((_) => _controllers[0].play());
        _initFirstThree();
        super.initState();
      }

      @override
      void deactivate() {
        _controllers[currentIndex].setVolume(0.0);
        _controllers[currentIndex].pause();
        super.deactivate();
      }

      @override
      void dispose() {
        _controllers.forEach((con) {
          con.dispose();
        });
        super.dispose();
      }

      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text('Swiper'),
            actions: <Widget>[
              new IconButton(
                icon: new Icon(Icons.disc_full),
                onPressed: () {
                  Navigator
                      .of(context)
                      .push(MaterialPageRoute(builder: (context) => Dissmiss()));
                },
              )
            ],
          ),
          body: new NotificationListener(
            onNotification: _didGetNotification,
            child: new Swiper(
              itemCount: 6,
              itemBuilder: (BuildContext context, int index) {
                return _controllers[index].value.initialized
                    ? new AspectRatio(
                        aspectRatio: _controllers[index].value.aspectRatio,
                        child: new VideoPlayer(_controllers[index]),
                      )
                    : new Center(child: new CircularProgressIndicator());
              },
              loop: urls.length > 6 ? true : false,
              onIndexChanged: (i) async {
                currentIndex = i;
                final int pauseIndex = i == 0 ? 5 : i - 1;
                await _controllers[pauseIndex].pause().then((_) async {
                  await _controllers[i].play();
                });
              },
            ),
          ),
        );
      }
    }
Daibaku
  • 11,416
  • 22
  • 71
  • 108

0 Answers0