【问题标题】:How to dispose a sibling of parent widget on navigation如何在导航上处理父小部件的同级
【发布时间】:2023-03-07 13:00:01
【问题描述】:

这是我的小部件的层次结构:

VideoPage
    VideoPlayer
    RelatedVideos
        VideoItem1
        VideoItem2
        VideoItem3

每当单击 VideoItem 时,我都会导航到新的 VideoPage。我的问题是 VideoPlayer (Chewie) 没有被处理,所以视频一直在后台播放。

我将如何处理来自 VideoItem 的 VideoPlayer Widget?

我尝试了 Navigator.pushReplacement,但无法返回到上一个视频。

这是处理导航的 VideoItem 小部件中代码的 sn-p(缩略图被一个手势检测器包裹,点击时会打开一个新页面):

GestureDetector(
  onTap: (){
    Navigator.push(context, MaterialPageRoute(
      builder: (context) {
        return VideoPage(
          file: file,
          thumbnail: thumbnail,
          title: videoTitle,
          id: id,
        );
      },
    ));
  },
  child: Container(
    width: MediaQuery.of(context).size.width,
    height: 200.0,
    child: ExtendedImage.network(
      thumbnail,
      fit: BoxFit.fill,
      cache: true,
    )
  ),
)

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    您是在VideoPage 中的initState 中创建控制器吗?如果是这样,请尝试将同一小部件​​中的deactivate 覆盖到控制器的pausedispose。这应该在离开 VideoPage 时发生。

    然后,您可以尝试使用 didUpdateWidget 重新初始化任何在停用时释放的 controllers,方法是将当前控制器与传入的旧小部件控制器进行比较。

    
    @override
    void initState() {
      super.initState();
      _videoPlayerController = new....
      _chewieController = new....
    }
    
    @override
    void didUpdateWidget(VideoPage oldWidget) {
      super.didUpdateWidget(oldWidget);
      if (widget._videoPlayerController != oldWidget._videoPlayerController) {
        // new controller here
      }
    }
    
    @override
    void deactivate() {
      _videoPlayerController.pause();
      _videoPlayerController.dispose();
      _chewieController.dispose();
      super.deactivate();
    }
    

    关于停用的信息在这里:Deactivate

    【讨论】:

    • 覆盖停用似乎有效。我在 ChewieController 和 VideoController 上都调用了 pause(),但现在我收到此错误:“在构建期间调用了 setState() 或 markNeedsBuild()。”当我回到上一个视频时。
    • 在尝试了您的最新建议后,我仍然收到之前遇到的错误,但现在我也收到“处理后使用了 ChewieController。”。这是 VideoPlayer 小部件的代码,如果我正确地按照您的说明进行操作,请告诉我:gist.github.com/jinyus/4eb77d2e3de7487386506fc8f729cbd5
    【解决方案2】:

    您可以将控制器传回另一个视图并处理掉它们:

    Navigator.push(context, MaterialPageRoute(
      builder: (context) {
        return VideoPage(
          file: file,
          thumbnail: thumbnail,
          title: videoTitle,
          id: id,
        );
      },
    )).then((List<ChewieController> controllers){
      controllers.forEach((controller) => controller.dispose())
    });
    

    【讨论】:

    • 我已经这样做了,问题是当我使用 Navigator.push() 时没有调用 dispose 方法...只有当我通过调用 Navigator 从堆栈中删除路由时才会调用它。 pushReplacement() 而是使用此方法不允许返回到上一个视频。
    • 最坏的情况下,您可以将控制器传递到下一个视图并在那里处理它们。
    • 我已更改答案以符合我之前的评论。
    • 试过了,它有效,但它太乱了。我使用了@yusef-ouda 建议的方法,但遇到了另一个障碍。编辑:此评论是对您最坏情况的回应。
    • 是的,确实感觉有点乱。
    猜你喜欢
    • 1970-01-01
    • 2021-04-13
    • 2020-12-17
    • 2019-08-14
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多