android - 带有 ViewModel 组件的 MVP
问题描述
免责声明:这不是 MVP 与 MVVM 的帖子。
我做了一个简单的项目来看看 MVP 是如何工作的
我的活动:
class MainActivity : AppCompatActivity(), MainContract.View {
lateinit var presenter: MainPresenter
private val counter by lazy { findViewById<TextView>(R.id.value_tv) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
presenter = MainPresenter(this)
increment_value_btn.setOnClickListener {
presenter.incrementCount()
}
decrement_value_btn.setOnClickListener {
presenter.decrementCount()
}
}
override fun updateCount(count: Int) {
counter.text = count.toString()
}
}
我的主持人:
class MainPresenter(mainView: View) : Presenter {
var view: View = mainView
var counter: Int = 0
override fun incrementCount() {
counter++
view.updateCount(counter)
}
override fun decrementCount() {
counter--
view.updateCount(counter)
}
}
当配置改变(方向)我的号码被重置。我知道这是一种正常行为,因为活动被删除并重新创建。我读过viewmodel旨在帮助数据生存。但是我不知道如何用我的演示者来实现它。
解决方案
我会推荐以下方法
首先创建一个基本的演示者界面,如下所示
interface BasePresenter<View : BaseView> : LifecycleObserver {
var view: View?
var viewLifecycle: Lifecycle?
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun attachView(view: View, viewLifecycle: Lifecycle?) {
this.view = view
this.viewLifecycle = viewLifecycle
viewLifecycle?.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
override fun onViewDestroyed() {
view = null
viewLifecycle = null
}
}
然后,您可以选择创建具有基本操作的基本视图界面
interface BaseView {
fun showProgressDialog()
fun hideProgressDialog()
}
你的演讲者班级应该看起来像
class MainPresenter() : BasePresenter<MainView> {
var counter: Int = 0
override fun incrementCount() {
counter++
view?.updateCount(counter)
}
override fun decrementCount() {
counter--
view?.updateCount(counter)
}
}
然后无论您在哪里初始化演示者实例,都不要忘记附加视图实现,如下所示
presenter.attachView(this, lifecycle)
此实现的解释
Presenter 扩展 ViewModel 可能看起来很奇怪,但我们不要将它与 MVVM 中的 ViewModel 混淆——AC 中的 ViewModel 是“旨在以生命周期意识的方式存储和管理 UI 相关数据”,这正是我们想要实现的
通过扩展 ViewModel,Presenter 实例将在配置更改后继续存在
通过传递和观察 viewLifecycle 每个 Presenter 将在视图被销毁之前自动将其视图引用设置为 null
推荐阅读
- sql - 如何将excel中的列放入sql中的IN函数?
- excel - 从单元格VBA excel中获取显式工作表超链接
- php - 我是否在 PHP 的 NumberFormatter 的“formatCurrency”函数中发现了一个错误?
- git - git rebase 后分离的 HEAD 警告
- python - “工作簿”对象没有属性“add_chart”
- node.js - 使用 Mocha 和 Chai 测试 JWT 身份验证
- javascript - TypeError:无法读取 ProductList.js 中未定义的属性“地图”
- tensorflow - 保存和加载 GAN 模型以使用 Keras 继续训练
- graphql - 是否可以在订阅注册时使用 HotChocolate 推送有效负载?
- python - 满足第一个条件后执行第二个更新语句