假设基于 MVP 模式实现了一个登录功能,其中模型(LoginInteractor)将使用活动上下文。
因此,我们必须实现以下类:LoginActivity、LoginPresenterImpl 和 LoginInteractorImpl(作为 MVP 模型)。正如 MVP 所述,我们将在 View 和 Presenter 之间定义一个契约。我们将它们命名为 LoginView 和 LoginPresenter。此外,我们还将为 Interactor 类定义一个接口,LoginInteractor。
LoginActivity 具有对LoginPresenter 的引用,所有逻辑都将在其中处理。具体实现LoginPresenterImpl参考LoginView和LoginInteractor。交互器的具体实现,LoginInteractorImpl 将使用活动上下文来初始化 Android 特定资源,这些资源是收集登录过程所需数据所必需的。
这样,presenter 逻辑与 android 资源无关,并且可以轻松进行单元测试。
示例代码 sn-p(请注意,演示者如何只知道抽象交互器。具体交互器在视图中初始化,并提供它的活动上下文。)
首先,我们为所有类定义契约:
interface LoginView {
fun onLoginSuccess()
fun onLoginFailed()
fun showErrorMessage(error: String)
//...........
}
interface LoginPresenter {
fun proceedLogin(username: String, password: String)
//............
}
interface LoginInteractor {
fun getUserByUsername(username: String) : User
fun getUserCredentials() : Credential
//............
}
然后,他们的具体实现:
class LoginActivity : LoginView, AppCompatActivity() {
private lateinit var presenter: LoginPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
// initialize presenter
presenter = LoginPresenterImpl(
view = this,
interactor = LoginInteractorImpl(this)
)
// your code goes here
}
override fun onLoginSuccess() {
// your code goes here
}
override fun onLoginFailed() {
// your code goes here
}
override fun showErrorMessage(error: String) {
// your code goes here
}
}
class LoginPresenterImpl(
private val view: LoginView,
private val interactor: LoginInteractor
) : LoginPresenter {
override fun proceedLogin(username: String, password: String) {
// your custom login logic goes here
// call interactor to get data
// process data
// give feedback to view
}
}
class LoginInteractorImpl(context: Context) : LoginInteractor {
override fun getUserCredentials() {
// your code goes here
}
override fun getUserByUsername(username: String) {
// use context to access local DB...
}
}
注意:为了更好地分离关注点,使用依赖注入解决方案将消除视图正在初始化所有其他对象这一事实所引起的问题。