原始答案
我在 Flutter 上使用 Getx 状态管理。
尽可能简化:
我构建了一个 GetxController 来控制我的页面,并且在这个控制器中我有一个 StatefulWidget 实例,它可以唤起 http 请求。
class MyController extends GetxController {
Player player;
}
class Player extends StatefulWidget {
PlayerState state;
@override
PlayerState createState() {
state = PlayerState();
return state;
}
}
class PlayerState extends State<Player> {
void methodName async() {
futureRequest().then((data) {
// when the error ocurrs
setState(() {});
});
}
}
当用户在请求结束之前关闭移动页面,触发控制器的 close 方法时,就会出现问题。
这样,当 setState 被触发时,没有更多的页面实例,就会发生错误。
我相信解决方案是在调用控制器关闭方法时中断与此 GetxController 相关的所有请求并“删除”此 StatefulWidget 实例。
我不知道这是否正确,如果它是如何做到的..
==================================================== =================
更新的答案
主要问题是 getDetails() 方法中的异步请求,即使在控制器被释放后,即使使用 GetBuilder 也会返回响应,并且该响应带有来自 videoPlayerController(video_player 插件实例)启动的视频的 url。
因此,用户在另一个屏幕上,但继续收听在后台播放的视频。
作为一种解决方法并考虑将良好实践应用于代码,我按照 GetX 规则进行了重构以仅使用无状态小部件。我解决了这个问题,但我必须将Future转换为Stream
正在使用 Get.lazyPut() 创建绑定以执行依赖项注入:
class Binding implements Bindings {
Get.lazyPut<PlayerController>(() {
return PlayerController(videoRepository: VideoRepository(VideoProvider(Dio())));
});
}
此绑定链接到基于 GetX 文档的页面路由器。
class AppPages {
static final routes = [
GetPage(name: Routes.MyRoute, page: () => MyPage(), binding: MyBinding()),
];
}
为了防止控制器在处置之前采取行动,我必须创建一个 Stream 并在控制器处置时取消它。
class MyController extends GetxController {
MyController({@required this.repository}) : assert(repository != null);
StreamSubscription<bool> stream;
// Instance of plugin video_player
VideoPlayerController videoPlayerController;
@override
void onClose() {
if (streamGetVideo != null) streamGetVideo.cancel();
super.onClose();
if (videoPlayerController != null) videoPlayerController?.dispose();
}
// This is the method called by the user on screen
void loadVideo() {
stream = getDetails().asStream().listen((bool response) {
// This code is canceled on onClose() method by the stream
if (response) update();
});
}
Future<bool> getDetails() async {
return await repository.getDetails().then((data) async {
videoPlayerController = VideoPlayerController.network(data);
initFuture = videoPlayerController.initialize();
await initFuture.whenComplete(() { return true; });
});
}
}
我认为 Flutter/GetX 应该有更好的方法来做到这一点,没有我做的这些变通方法。如果有人有更好的方法或提示,我愿意接受建议。