class LoginContract {
interface View {
fun showLoginState(loginState: LoginState)
}
interface Presenter {
fun viewCreated()
fun viewDestroyed()
fun login(email: String, password: String)
fun logout()
}
}
Model
interface LoginRepository {
fun login(email: String, password: String): LoginState
fun logout(): LoginState
}
class LoginRepositoryImpl : LoginRepository {
override fun login(email: String, password: String): LoginState {
// do login
return LoginState.Login(email)
}
override fun logout(): LoginState {
// do logout
return LoginState.Logout
}
}
View
View 只需要做兩件事:
通知 Presenter 有關於 View 的生命週期,或是使用者的輸入。
實現 Contract 的 View 介面,來顯示資料。
class MvpActivity : ViewBindingBaseActivity<ActivityMvpBinding>(), LoginContract.View {
override val viewBindingFactory: (layoutInflater: LayoutInflater) -> ActivityMvpBinding
get() = ActivityMvpBinding::inflate
private val presenter: LoginContract.Presenter by lazy {
LoginPresenter(this, LoginRepositoryImpl())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 登入
binding.loginButton.setOnClickListener {
presenter.login("email", "password")
}
// 登出
binding.logoutButton.setOnClickListener {
presenter.logout()
}
// 通知viewcreate
presenter.viewCreated()
}
override fun showLoginState(loginState: LoginState) {
when (loginState) {
is LoginState.Login -> {
Toast.makeText(this, "登入成功 ${loginState.loginEmail}", Toast.LENGTH_SHORT).show()
}
is LoginState.Logout -> {
Toast.makeText(this, "登出掰掰", Toast.LENGTH_SHORT).show()
}
}
}
override fun onDestroy() {
super.onDestroy()
// 通知view destroy
presenter.viewDestroyed()
}
}
Presenter
LoginPresenter要實現 Contract 的 Presenter 介面,Presenter 同時擁有 View 和 Model 的參考。
class LoginPresenter(
private var view: LoginContract.View?,
private val model: LoginModel
) : LoginContract.Presenter {
override fun viewCreated() {
updateLoginState()
}
override fun viewDestroyed() {
view = null
}
override fun login(email: String, password: String) {
model.login(email, password)
updateLoginState()
}
override fun logout() {
model.logout()
updateLoginState()
}
private fun updateLoginState() {
val loginEmail = model.getLoginAccount()?.email ?: ""
val loginState = if (loginEmail.isEmpty()) {
LoginState.Logout
} else {
LoginState.Login(loginEmail)
}
view?.showLoginState(loginState)
}
}