Это будет длинный пост о том, как структурировать проект MVP, прежде чем приступать к решению вашей проблемы в самом конце моего ответа.
Я просто сообщаю структуру MVP здесь how to structure MVP project от моего собственного ответа.
Я часто ставил код бизнес-логики в Модельный слой (не путайтесь с моделью в базе данных). Я часто переименовываю как XManager
, чтобы избежать путаницы (например, ProductManager
, MediaManager
...), поэтому класс-презентатор просто использует для поддержания рабочего процесса.
Правило большого пальца не ограничено или, по крайней мере, ограничено пакет андроидного импорта в классе презентатора. Эта лучшая практика помогает вам легче тестировать класс презентатора, потому что ведущий теперь просто простой Java-класс, поэтому нам не нужна инфраструктура Android для тестирования этих вещей.
Например, это мой рабочий процесс mvp.
Просмотреть класс: Это место, где вы храните все свое видение, такое как кнопка, textview ... и вы устанавливаете для всех этих компонентов на этом уровне все слушатели. Также в этом представлении вы определяете класс Listener для презентационных инструментов позже. Компоненты вашего представления вызовут методы в этом классе слушателя.
class ViewImpl implements View {
Button playButton;
ViewListener listener;
public ViewImpl(ViewListener listener) {
// find all view
this.listener = listener;
playButton.setOnClickListener(new View.OnClickListener() {
listener.playSong();
});
}
public interface ViewListener {
playSong();
}
}
Presenter класс: Это где вы храните вид и модель внутри для вызова позже. Также класс презентатора будет реализовывать интерфейс ViewListener, определенный выше. Основной точкой ведущего является рабочий процесс логики управления.
class PresenterImpl extends Presenter implements ViewListener {
private View view;
private MediaManager mediaManager;
public PresenterImpl(View, MediaManager manager) {
this.view = view;
this.manager = manager;
}
@Override
public void playSong() {
mediaManager.playMedia();
}
}
класс менеджер: Вот основной код бизнес-логики. Возможно, у одного ведущего будет много менеджеров (зависит от того, как усложнять представление). Часто мы получаем класс Context
через некоторые рамки для инъекций, такие как Dagger
.
Class MediaManagerImpl extends MediaManager {
// using Dagger for injection context if you want
@Inject
private Context context;
private MediaPlayer mediaPlayer;
// dagger solution
public MediaPlayerManagerImpl() {
this.mediaPlayer = new MediaPlayer(context);
}
// no dagger solution
public MediaPlayerManagerImpl(Context context) {
this.context = context;
this.mediaPlayer = new MediaPlayer(context);
}
public void playMedia() {
mediaPlayer.play();
}
public void stopMedia() {
mediaPlayer.stop();
}
}
Наконец: Положите эти вещи вместе в деятельности, Fragments ... Вот место инициализации вида, менеджер и назначить всех ведущий.
public class MyActivity extends Activity {
Presenter presenter;
@Override
public void onCreate() {
super.onCreate();
IView view = new ViewImpl();
MediaManager manager = new MediaManagerImpl(this.getApplicationContext());
// or this. if you use Dagger
MediaManager manager = new MediaManagerImpl();
presenter = new PresenterImpl(view, manager);
}
@Override
public void onStop() {
super.onStop();
presenter.onStop();
}
}
Вы видите, что каждый презентатор, модель, вид завернут одним интерфейсом. Эти компоненты будут вызваны через интерфейс. Эта конструкция сделает ваш код более надежным и более легким для последующего изменения.
Короче говоря, в вашей ситуации, я предлагаю эту конструкцию:
class ViewImpl implements View {
Button button;
TextView textView;
ViewListener listener;
public ViewImpl(ViewListener listener) {
// find all view
this.listener = listener;
button.setOnClickListener(new View.OnClickListener() {
textView.setText(resource_id);
});
}
}
В случае, если вид логики является сложным, например, некоторые условия для установки значения. Поэтому я верну текст в DataManager
. Например:
class Presenter {
public void setText() {
view.setText(dataManager.getProductName());
}
}
class DataManager {
public String getProductName() {
if (some_internal_state == 1) return getResources().getString(R.string.value1);
if (some_internal_state == 2) return getResources().getString(R.string.value2);
}
}
Таким образом, вы никогда не ставили связанные с андроидом вещи в класс презентатора. Вы должны переместить это значение в класс View
или класс DataManager
в зависимости от контекста.
Это очень длинное сообщение, в котором подробно обсуждается MVP и как решить вашу конкретную проблему. Надеюсь, эта помощь :)
Чем больше я использую MVP с Android, тем больше я задаю эти вопросы. Ресурсы и объект Context действительно трудно искоренить. Вы нашли удовлетворительное решение? – loeschg
взгляните на эту статью и образец проекта, который может помочь: https://medium.com/@m_mirhoseini/yet-another-mvp-article-part-1-lets-get-to-know-the-project- d3fd553b3e21 # .6y9ze7e55 –