Предположим, что реализована функция входа в систему на основе шаблона MVP, где модель (LoginInteractor) будет использовать контекст действия.
Итак, нам нужно реализовать следующие классы: LoginActivity
, LoginPresenterImpl
и LoginInteractorImpl
(как модель MVP).Как заявляет MVP, мы определим контракт между View и Presenter.Мы называем их LoginView
и LoginPresenter
.Кроме того, мы также определим интерфейс для класса Interactor, LoginInteractor
.
. LoginActivity
имеет ссылку на LoginPresenter
, где будет обрабатываться вся логика.Конкретная реализация LoginPresenterImpl
имеет ссылку на LoginView
и LoginInteractor
.Конкретная реализация для интерактора, LoginInteractorImpl
будет использовать контекст активности для инициализации специфических ресурсов Android, которые необходимы для сбора данных, необходимых во время процесса входа в систему.
Таким образом, логика презентатора остается независимой от ресурсов Androidи это может быть легко проверено модулем.
Пример фрагмента кода (обратите внимание, что докладчик знает только об абстрактном Interactor. Конкретный интерактивный объект инициализируется в представлении, обеспечивая его контекст действия.)
Сначала мы определим контракт для всех классов:
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...
}
}
Примечание: для лучшего разделения интересов с помощью внедрения зависимостейРешение устранит проблемы, возникающие из-за того, что View инициализирует все другие объекты.