jhomlala / betterplayer

Better video player for Flutter, with multiple configuration options. Solving typical use cases!
Apache License 2.0
920 stars 983 forks source link

setState() or markNeedsBuild() called when widget tree was locked. This BetterPlayerSubtitlesDrawer widget cannot be marked as needing to build because the framework is locked. #1087

Open h-unterp opened 1 year ago

h-unterp commented 1 year ago

History check I am aware of https://github.com/jhomlala/betterplayer/issues/673 However, I copied the example from https://github.com/jhomlala/betterplayer/tree/master/example/lib/pages/video_list You will see my code is nearly 1:1 with your example.

See how I am calling VideoListWidget: https://github.com/h-unterp/better_scroll/blob/4a91bace0eb309e353fa72439b6b398d33fa55c3/lib/easy_example.dart#L55

Describe the bug Combining https://github.com/ftognetto/riverpod_infinite_scroll with better player Scroll down a few dozen (0-30) videos and you will see the bug.

To Reproduce Steps to reproduce the behavior:

  1. Build https://github.com/h-unterp/better_scroll
  2. Scroll down a few dozen (0-30) videos and you will see the bug.

Screenshots

Screen Shot 2022-09-24 at 6 27 49 AM Screen Shot 2022-09-24 at 6 27 45 AM Screen Shot 2022-09-24 at 6 27 40 AM

Flutter doctor

hunterp@H better_scroll % flutter doctor -v
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.6 21G115 darwin-arm, locale en-US)
    • Flutter version 3.0.5 at /users/hunterp/dev/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision f1875d570e (2 months ago), 2022-07-13 11:24:16 -0700
    • Engine revision e85ea0e79c
    • Dart version 2.17.6
    • DevTools version 2.12.2

[✓] Xcode - develop for iOS and macOS (Xcode 14.0)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.3

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).

[✓] VS Code (version 1.71.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.48.0

[✓] Connected device (4 available)
    • Hunter’s iPhone (mobile)         • ios          • iOS 16.0 20A362

[✓] HTTP Host Availability
    • All required HTTP hosts are available

Better Player version

tianliqiang1201 commented 1 year ago

i have the same question,I want to know how to solve this problem

osmansimsek commented 1 year ago

do you have any solution to this problem? @jhomlala How we can solve this problem

BrightDV commented 1 year ago

Any update?

Maqcel commented 1 year ago

Same issue here, on entering full screen on chat (flutter_chat_ui), it's disposing video player controller and throwing setState error

Wanjuuuuu commented 1 year ago

I had a similar issue with my project.

If you are using list view with player, then please investigate whether your list item widget is kept or not. I mean finding out if it's disposed and initialized again.

I just made a list view by myself with SliverList, and list item widget was just disposed by framework right after entering better player's full screen mode. So widget tree is locked due to widget's disposal, though, BetterPlayerController is still working and its state is keeping changed.

In this case, you'd better implement AutomaticKeepAliveClientMixin for widget which contains BetterPlayerController.

You can override wantKeepAlive as true to prevent widget from disposal.

  @override
  bool get wantKeepAlive => isVideoFullScreen;

When you use flag, then must let flutter know it's updated using updateKeepAlive.

    switch (event.betterPlayerEventType) {
      case BetterPlayerEventType.openFullscreen:
        debugPrint(
            'openFullscreen: ${event.betterPlayerEventType}, ${_betterPlayerController!.isFullScreen}');
        // Keep Alive as true to prevent widget disposed during full view
        isVideoFullScreen = true;
        updateKeepAlive();
        break;
      case BetterPlayerEventType.hideFullscreen:
        debugPrint(
            'hideFullscreen: ${event.betterPlayerEventType}, ${_betterPlayerController!.isFullScreen}');
        // Keep Alive as true until completing back to normal video view
        Future.delayed(const Duration(seconds: 3), () {
          isVideoFullScreen = false;
          updateKeepAlive();
        });
        break;
      default:
        break;
    }