Должна ли модель MVP содержать специальный термин для Android?

Я могу делать логические вещи внутри представления MVP, но, насколько я знаю, согласно шаблону MVP представление должно быть настолько тупым, насколько это возможно. Может ли модель MVP содержать определенный термин для Android? Если нет, то как я могу использовать контекст активности внутри модели MVP?


person Newaj    schedule 13.03.2019    source источник
comment
Используйте класс, который использует контекст Activity в качестве детали реализации.   -  person EpicPandaForce    schedule 13.03.2019
comment
Создайте класс, получите Контекст в качестве аргумента конструктора, выставьте метод, который не знает о Контексте, а затем в своем Презентаторе или что-то еще, что вы получаете свой класс вместо Контекста напрямую.   -  person EpicPandaForce    schedule 13.03.2019
comment
Можете ли вы найти мне вариант использования, в котором вы хотите достичь, я лично передаю значения, связанные с активностью, как конструктор, но не контекст.   -  person Manoj Perumarath    schedule 21.03.2019
comment
@ManojPerumarath Для чего-то вроде: context.getSystemService() внутри модели MVP. Для проверки интернет-соединения.   -  person Newaj    schedule 21.03.2019
comment
Что я сделал, так это создал утилиты для проверки сети и использовал их перед вызовом методов докладчика, я думаю, что это использование не нарушит правила использования MVP.   -  person Manoj Perumarath    schedule 21.03.2019
comment
Это означает, что вы проверяете сеть внутри View/Presenter? Не в модели?   -  person Newaj    schedule 21.03.2019
comment
никогда не используйте контекст активности вне активности/фрагмента/представления, вместо этого вы можете использовать applicationContext   -  person svkaka    schedule 21.03.2019


Ответы (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 инициализирует все остальные объекты.

person Bagoly Sz.    schedule 16.03.2019
comment
У меня есть 2 вопроса: а) LoginInteractorImpl - это модель MVP, и вы использовали там Context. Мое замешательство здесь, не означает ли это (Контекст) использование термина Android внутри модели? б) Вы создали ссылку на LoginInteractorImpl внутри MVP View (активности), разве она не создает связь между Model и View? Я новичок в MVP и не понимаю эти 2 пункта. - person Newaj; 17.03.2019
comment
Да, ты прав. Для лучшего разделения интересов следует использовать фабричный метод и инструменты внедрения зависимостей, такие как Dagger или Коин. В некоторых случаях использование контекста неизбежно, особенно когда источником данных является какой-то ресурс, специфичный для Android. То, как вы хотите это сделать, - скрыть конкретную реализацию за абстрактным классом/интерфейсом. - person Bagoly Sz.; 18.03.2019
comment
Вы передаете контекст интерактору, это неплохо, так как он не хранится как свойство. Но все же с точки зрения юнит-тестирования было бы лучше пройти что-то более связанное с конкретным случаем. Если вы используете контекст для извлечения строк, вы можете определить LocalizationProvider или StringProvider и передать его внутри интерактора. Было бы легче издеваться над тестами, да и разделение слоев лучше. - person Yurii Tsap; 21.03.2019