MVP模式中Presenter怎么安全更新视图状态?
我在用MVP写登录功能时遇到问题,Presenter怎么安全更新视图状态呢?
现在尝试把登录逻辑放在Presenter里处理,但直接调用view.showLoading()时发现:
class LoginPresenter {
constructor(view) {
this.view = view; // 这里持有view引用会不会有问题?
}
login() {
api.login().then(() => {
this.view.showSuccess(); // 这样写会不会导致内存泄漏?
});
}
}
当用户快速切换页面时偶尔出现view已经销毁但Presenter还在执行的情况。试过用WeakMap弱引用,但发现view属性会变成undefined。有没有更好的解耦方式?
在Presenter里加个标记位,用来判断view是否还存活,调用view方法前先检查下
页面销毁的时候记得调
presenter.detachView(),把引用清掉。别嫌麻烦,这一步很关键。其实很多框架都有类似的实现,像RxJava有Disposable,Kotlin有协程取消机制。但最简单粗暴的方式还是这种标记法,兼容性好,不容易出幺蛾子。
对了,WeakMap那条路走不通的,弱引用hold不住对象,随时可能被回收,业务场景基本没法用。
最简单的办法是在Presenter里加个标志位,标记View是否还有效。比如这样:
然后在你的页面组件销毁的时候记得调用
presenter.detachView()就行了。WeakMap其实不太适合这里,因为一旦View被回收,你就没法更新界面了,而且调试起来特别痛苦。
另外建议把View做成接口形式,Presenter只依赖抽象方法,这样以后替换实现也方便。我之前就是没做这一步,后来加单元测试的时候折腾半天。
这种模式虽然多写几行代码,但能避免大部分内存泄漏和空指针问题。希望能帮到你。