将特定于应用程序的逻辑添加到Presenter的首选方法是什么? (MVP)

时间:2019-06-17 19:08:29

标签: android kotlin architecture mvp android-mvp

假设我要使用MVP(在Android上会更详细)。有关如何执行此操作的文章很多。但是,尚不清楚如何在其中添加应用特定的逻辑?

示例:我想让用户键入host和port并使用该数据创建app-global服务器api impl(比如说Retrofit实例)。

所以我有Contract和Base ..接口:

/**
 * MVP : Presenter (Passive View flavor)
 */
interface Presenter : BasePresenter<View>

/**
 * MVP : View (Passive View flavor)
 */
interface View : BaseView<Presenter> {
    var host: String
    var port: String

    fun showValidationError(error: Exception)
}

interface BasePresenter<ConcreteView> {
    fun onModelChanged()
    fun onViewChanged()

    fun attachView(view: ConcreteView)
    fun detachView()
}

interface BaseView<ConcretePresenter> {
    var presenter: ConcretePresenter?
}

型号:

/**
 * MVP : Model
 */
class Model(
    _host: String = "",
    _port: UInt = 0U) {

    // we could add presenter notification on both `host` and `port` changed,
    // but we need it to be notified once only when both are set

    var host = _host
        private set

    var port: UInt = _port
        private set

    fun update(host: String, port: UInt) {
        this.host = host
        this.port = port

        presenter?.onModelChanged()
    }

    var presenter: Presenter? = null
}

演示者:

class PresenterImpl(val model: Model) : Presenter {

    private var view: View? = null

    override fun attachView(view: View) {
        if (this.view != null) {
            detachView()
        }

        this.view = view
        this.view?.presenter = this

        updateView()
    }

    private fun updateView() {
        view?.let {
            it.host = model.host
            it.port = model.port.toString()
        }
    }

    // as Model observer
    override fun onModelChanged() {
        view?.let { updateView() }
    }

    // as View observer

    override fun onViewChanged() {
        view?.let {
            if (!isValidView(it)) {
                return
            }
            model.update(it.host, it.port.toUInt())
        }
    }

    private fun isValidView(view: View): Boolean {
        try {
            if (view.host.isEmpty())
                throw Exception("Host can not be empty")

            if (view.port.isEmpty())
                throw Exception("Port can not be empty")

            if (view.port.toUIntOrNull() == null)
                throw Exception("Port is expected to be positive Number")
        } catch (e : Exception) {
            view.showValidationError(e)
            return false
        }
        return true
    }

    override fun detachView() {
        view?.presenter = null
        view = null
    }
}

为简单起见,我们将“活动”用作“视图”隐式实现,并且所有内容都链接在一起(模型表示者视图)。

这是流程:

  1. 用户在EditText中键入主机和端口,然后单击“确定”按钮。
  2. View通过onViewChanged通知Presenter
  3. 演示者从View(view.hostview.port)请求数据,对其进行验证并使用model.update()更新模型。
  4. 模型更新数据并通过onModelChanged()通知Presenter
  5. 现在,Presenter应该执行特定于应用程序的逻辑-使用模型数据创建Retrofit实例。

第5步可以作为第3步的延续(而不是作为模型的侦听器)完成,但是它并没有明显改变。

最好的方法是什么?

这些选项是:

  1. 扩展Presenter隐含并覆盖onModelChanged()(不想仅仅使用继承)
  2. 添加Presenter侦听器界面并存储侦听器列表,并在onModelChanged()中更改模型时通知他们
  3. 您的答案

Presenter impl位于不依赖于Android的不同Gradle模块中,因此我不能只在onModuleChanged()的{​​{1}}中添加此应用专用代码。

0 个答案:

没有答案