How to dispose my VideoPlayerController when i shift my tab in flutter using GetX

84 views Asked by At

I am making a social media app in flutter where i am implementing reels and videos like youtube on separate tabs. I am using Video player package for that App is devided into tabs. using a tab controller and tabbed screen which is using bottom navigation bar with indexed stack to move the pages When the app starts you see the home page. But the problem is that all the init states are called whenever i shift tabs and the video controller in the init state of the reel item widget also gets called(which is inside my reels screen stateless widget which operates with getx). I dont want this. This creates two problems

  1. Many videoControllers get initialized everytime and i get the Exoplayer error of VideoPlayer
  2. Video in video screen or reel in reels screen continues to play even when i shift tabs(I cannot find a way to dispose video controllers of the children of reel screen and video screen on shifting tabs).

Tab screen

class TabbedScreen extends StatelessWidget {
  TabbedScreen({super.key});
  TabbedController controller = Get.find();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        bottomNavigationBar: Obx(
          () => BottomNavigationBar(
            currentIndex: controller.tabbingIndex.value,
            showSelectedLabels: false,
            showUnselectedLabels: false,
            selectedItemColor: Colors.yellow,
            unselectedItemColor: Colors.white,
            type: BottomNavigationBarType.fixed,
            backgroundColor: Color.fromARGB(255, 71, 71, 71),
            items: [
              const BottomNavigationBarItem(
                icon: Icon(
                  Icons.home_outlined,
                ),
                label: 'Home',
              ),
              BottomNavigationBarItem(
                icon: ImageIcon(
                  AssetImage(ImageConstant.trending),
                ),
                label: 'trending',
              ),
              BottomNavigationBarItem(
                icon: ImageIcon(AssetImage(ImageConstant.reels)),
                label: 'Reels',
              ),
              BottomNavigationBarItem(
                icon: Icon(
                  Icons.add_circle_outline,
                ),
                label: 'Add',
              ),
              BottomNavigationBarItem(
                icon: ImageIcon(AssetImage(ImageConstant.verified_videos)),
                label: 'verified Vids',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.groups),
                label: 'groups',
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.account_circle_outlined),
                label: 'account',
              ),
            ],
            onTap: (value) {
              controller.setTabbingIndex(value);
            },
          ),
        ),
        body: Obx(
          () => IndexedStack(
            index: controller.tabbingIndex.value,
            children: [
              Home(controller.currentUser),
              TrendingScreen(controller.currentUser),
              ReelsScreen(controller.currentUser),
              AddContentScreen(controller.currentUser),
              VerifiedVidScreen(controller.currentUser),
              GroupsScreen(controller.currentUser),
              AccountScreen(controller.currentUser),
            ],
          ),
        ));
  }
}

Tabbed Controller

class TabbedController extends GetxController with GetTickerProviderStateMixin {
  User currentUser = Get.arguments['currentUser'];
  RxInt tabbingIndex = 0.obs;

  void setTabbingIndex(int value) {
    eliteVideoController.dispose();
    tabbingIndex.value = value;
  }
}

Reel item(Note: This is inside a reel screen stateless getx managed widget)

import 'package:bitfitx_project/core/utils/auth_constants.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';

class VideoPlayerItem extends StatefulWidget {
  final String videoUrl;
  const VideoPlayerItem({
    Key? key,
    required this.videoUrl,
  }) : super(key: key);

  @override
  _VideoPlayerItemState createState() => _VideoPlayerItemState();
}

class _VideoPlayerItemState extends State<VideoPlayerItem> {
  late VideoPlayerController videoPlayerController;

  @override
  void dispose() {
    videoPlayerController.dispose();
    print('i was disposed');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    videoPlayerController = VideoPlayerController.network(widget.videoUrl)
      ..initialize().then((value) {
        videoPlayerController.play();
        videoPlayerController.setVolume(1);
        videoPlayerController.setLooping(true);
      });
    final size = MediaQuery.of(context).size;

    return Container(
      width: size.width,
      height: size.height,
      decoration: const BoxDecoration(
        color: Colors.black,
      ),
      child: VideoPlayer(videoPlayerController),
    );
  }
}

This is all. Just like reel screen i use video controllers in other screens as well. If only use reel screen and turn off all the other screens for a while then reels play without the exoplayer error but they play even when the reels tab is not opened.

Things i tried

  1. Initializing the video controller inside the build method of reel item widget. I thought that will solve the problem of turning on the video everytime the app is loaded and all init states are called.
  2. I made a constants.dart file and created a video controller inside it and initialized it with dummy video in my assets. I planned that if i need a video controller anywhere in my files/screens i will reinitialize this controller and i can solve the problem of too many controllers. The result was that this controller gets initialized with my dummy video and gets disposed after sometime and when i try to use it inside the reels item widget. I get the error 'cannot use a widget after its been disposed'
0

There are 0 answers