0

We have a PageView (technically a PreloadPageView) that contains videos (they can be large). The way we are currently handling the playing/pausing is by having a separate GlobalKey() for each of them and calling globalKey.currentState.play()/.pause(). Now this is working fine, but since the GlobalKeys hold the references to the states of these videos, it never lets Flutter dispose these states, which leads to an OutOfMemory error.

We already tried to manually call globalKey.currentState.dispose(), the problem with that is we need to decide how many videos we keep in memory, which should be different depending on how large the videos are (some of them are using DASH, so only part of them are loaded, some of them are full videos) and it should preferably also be different for devices with different amount of free memory.

Ideally, Flutter should keep track of memory usage and should clear the pages from memory if there are too many, so the best solution would be letting it clear pages, but we also need to be able to play and pause those videos. One solution would be not using GlobalKeys and using props instead (e.g., to pass isPlaying prop to the video), however, it doesn't seem to be a good practice to mix declarative and imperative programming in this case and it would also make the code less readable.

Is there any way to still have a reference to the state (to be able to call play/pause imperatively), but let Flutter clear it from memory to avoid OOM errors?

András Geiszl
  • 966
  • 2
  • 16
  • 36
  • Please post code, I suspect the video player is not being disposed properly – PixelToast Sep 17 '22 at 21:05
  • The video player is not being disposed, but it's because it's held inside the state that we have a `GlobalKey` for. Isn't not disposing state that's held by a `GlobalKey` intentional? – András Geiszl Sep 19 '22 at 11:28
  • GlobalKey does not keep a widget alive, it just gives you access the State / BuildContext while it's still in the tree. – PixelToast Sep 19 '22 at 17:19
  • Every source that I can find says that if a widget have a `GlobalKey`, it will be reparented, when inserted back into the widget tree, therefore only `deactivate()` will be called, not `dispose()` (there's even a comment in SO that states this: https://stackoverflow.com/questions/56387243/difference-between-deactivate-and-dispose#comment-122421137). It's also our experience. We changed the logic not to use `GlobalKey`s (there wasn't any other change other than key management), and now it doesn't have the OOM problems. I just thought there would be a better solution. – András Geiszl Sep 20 '22 at 08:15
  • Actually, now that I think about it, we could've disposed the video player on `deactivate()`, but that still would have the issue of having to manually initialize it when it's reinserted into the tree. Using states has the advantage of not having to care about activation/deactivation and we can also use `PageStorageKey` to save the state while the page is not in the memory. – András Geiszl Sep 20 '22 at 08:23
  • The reparenting only happens when the GlobalKey is inserted on the same build phase that it was removed, verbatim from the docs: "a widget must arrive at its new location in the tree in the same animation frame in which it was removed from its old location in the tree" Regardless, I can't help with your OOM problem without seeing code. – PixelToast Sep 20 '22 at 15:20

0 Answers0