Я могу делать логические вещи внутри представления MVP, но, насколько я знаю, согласно шаблону MVP представление должно быть настолько тупым, насколько это возможно. Может ли модель MVP содержать определенный термин для Android? Если нет, то как я могу использовать контекст активности внутри модели MVP?
Должна ли модель MVP содержать специальный термин для Android?
Ответы (1)
Давайте предположим реализацию функции входа на основе шаблона MVP, где модель (LoginInteractor) будет использовать контекст действия.
Итак, нам нужно реализовать следующие классы: LoginActivity
, LoginPresenterImpl
и LoginInteractorImpl
(как модель MVP). Как утверждает MVP, мы определим контракт между представлением и презентатором. Мы называем их 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 инициализирует все остальные объекты.