Могу ли я зарегистрировать MVP Presenter внутри фрагмента
Я следовал шаблону MVP, предоставленному Google для реорганизации моего приложения. У меня есть одна MainActivity и много фрагментов, и мне кажется, что создавать действия для каждого фрагмента не так уж и сложно, поэтому я подумал зарегистрировать докладчика во фрагменте. Я вижу, что каждый фрагмент регистрирует своего собственного докладчика, но я не уверен, насколько это неправильно... :)
Итак, вот мой ведущий:
public class FirstPresenter implements FirstContract.Presenter {
private final FirstContract.View mView;
public FirstPresenter(FirstContract.View view) {
mView = view;
}
@Override
public void start() {
Log.e(TAG, "Start");
}
}
И вот мой фрагмент:
public class FirstFragment extends Fragment implements FirstContract.View {
private FirstContract.Presenter mPresenter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container
, Bundle savedInstanceState) {
...
// I register firstFragment presenter here.
mPresenter = new FirstPresenter(this);
...
Итак, мой вопрос, это правильный путь? Могу ли я зарегистрировать Presenter в Fragment вместо этого в Activity? И если это не правильный путь, есть ли хороший пример для обработки MVP с одним действием и несколькими фрагментами?
Спасибо, ребята, БР!
Ответы
Ответ 1
Как вы можете видеть в образцах Google https://github.com/googlesamples/android-architecture), Activities
create Presenters
. Кроме того, Views
присоединяется к Activity
и Presenters
в качестве параметра для получения представлений (Fragments
).
После выполнения Fragment
транзакции или состояния Fragment
(просмотра) восстановлено Presenters
создается и принимает Fragments
(views) как параметр, чем вызов
view.setPresenter(T presenter);
методы просмотров и Presenters
регистрируются для просмотра.
Я думаю, что создание Presenter
в Fragment
не является хорошей практикой. Прежде всего это отдельные слои. Это незаконно для Разделения проблем. Во-вторых, если вы создаете презентатор в Fragment
, вы привязываете свою жизнь Presenter к просмотру LifeCycle
, а когда Fragment
уничтожается и воссоздается, вы создаете нового ведущего, но это разные слои.
Модель - это интерфейс, определяющий отображаемые данные или иным образом действующие в пользовательском интерфейсе.
Ведущий действует на модель и представление. Он извлекает данные из репозиториев (модели) и форматирует их для отображения в представлении.
Представление - это пассивный интерфейс, который отображает данные (модель) и маршрутизирует пользовательские команды (события) ведущему, чтобы воздействовать на эти данные.
Итак, Activity
может действовать как overall controller
, который создает Presenters
и Views
и связывает их.
![введите описание изображения здесь]()
Если мы поговорим о вашем вопросе, да, вы можете зарегистрировать презентатор в фрагменте. Но вам следует избегать создания презентаторов в фрагментах, которые вы используете в качестве представления.
Но в Android-сообществе есть много разных подходов к шаблону MVP, как показано ниже.
https://plus.google.com/communities/114285790907815804707
Почему действия не являются элементами ui?
http://www.techyourchance.com/activities-android/
Ответ 2
Если вы используете одну единственную операцию для размещения нескольких фрагментов, а также используете Dagger 2 для инъекции нужного вам докладчика, вы можете напрямую внедрить каждого докладчика в каждый фрагмент.
Моя история использования
Я делаю проект с архитектурой через несколько месяцев, так как я узнал о Android Jetpack Navigation Component, я начал переносить все представления моего приложения в этот шаблон.
Итак, я столкнулся с большим количеством рефакторинга, выполняя процесс, и я был в этой ситуации, не зная, что делать с этой ситуацией.
Поскольку я использовал Dagger 2 с начальной точки, чтобы внедрить своих докладчиков в свои действия, это не сильно изменится, если сделать то же самое, но с фрагментами.
Я наткнулся на тот же репозиторий, чтобы проверить, как должна следовать архитектура с фрагментами, что действительно является хорошим способом создания экземпляра презентатора внутри хоста Activity, если у вас есть только 1 фрагмент в качестве дочернего элемента.
Дело в том, что если мне нужно иметь несколько фрагментов внутри одного хоста Activity, я должен создать экземпляр каждого докладчика и пропустить его через мой FragmentManager внутри каждого фрагмента, и я думаю, что это не то, на что я смотрел, поскольку он добавляет несколько экземпляров объекта. ведущий от Host Activity.
Это приводит к одному случаю, имеющему несколько экземпляров внутри моей активности хоста для всех докладчиков, а также некоторые интерфейсы для обработки отсоединения заданий/представлений при необходимости.
Один простой способ сделать это с несколькими фрагментами - просто не думать об активности хоста и вводить презентаторов внутри каждого фрагмента.
Делая это с Dagger, он делает инъекцию чище.
Взгляните на простой пример
class MainMenuActivity : BaseActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
inflateMainFragment(savedInstanceState)
}
override fun getLayout(): Int {
return R.layout.activity_main_menu
}
fun inflateMainFragment(savedInstanceState: Bundle?){
if (savedInstanceState == null) {
val fragment = MainMenuFragment()
supportFragmentManager
.beginTransaction()
.add(R.id.nav_host_fragment, fragment)
.commit()
}
}
}
Как вы можете видеть, здесь у меня нет экземпляров каких-либо презентаторов, в которых может нуждаться моя навигация. Вместо этого я просто вставляю каждого нужного докладчика в каждый фрагмент
class MapsFragment: BaseMapFragment(), MapContract.MapView {
private lateinit var mMap: GoogleMap
@Inject
lateinit var presenter: MapsPresenter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_paseo,container,false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(requireActivity().application as YawpApplication).getAppComponent()?.inject(this)
presenter.attachView(this)
setupToolbar()
setupMap()
}
}
А используя жизненный цикл фрагментов, вы можете отсоединить все ваши представления фрагментов в onDestroyView()
, а также сэкономить некоторое пространство памяти при запуске сборщика мусора.
override fun onDestroyView() {
super.onDestroyView()
presenter.detachView()
presenter.detachJob()
}
На официальном репозитории Google я нашел вопрос, который помог мне понять его лучше.
Вы можете проверить это здесь