2015-12-13 4 views
33

У меня есть активность с двумя фрагментами в ней.MVP для активности с несколькими фрагментами

Активность (MainActivity) извлекает данные из открытой погоды api. Я реализовал MVP для этого, в которых: Model содержит все объекты ответа от API
View является Activity
Presenter содержит MainPresenter, MainPresenterImpl, MainView, GetDataInteractor и GetDataInteractorImpl.

Таким образом, активность получает данные из веб-службы. Оба фрагмента будут отображать данные из данных, полученных в ходе операции.

Какова наилучшая практика использования MVP в этой ситуации? Я знаю, как передавать данные между фрагментами < -> активность через интерфейс/обратные вызовы, мой вопрос заключается в изменении этого поведения при реализации MVP?

+1

Только что подумал: я бы рассмотрел фрагменты, которые будут считаться как Views (в отношении MVP), поэтому я задаюсь вопросом, было бы странно иметь одну презентацию, ссылающуюся на несколько представлений (точнее, на их обратные вызовы) для отображения разных данных в наиболее подходящем представлении для этого? Я думаю, что ведущий должен решить/направить, какое представление отображает данные? P.s. По-видимому, несколько презентаторов для одного представления - это действительный подход, поэтому, возможно, работает и наоборот: http://stackoverflow.com/a/2068/1041533 – AgentKnopf

+2

@AgentKnopf на самом деле, как указано здесь http://programmers.stackexchange.com/a/261351/206366 в MVP каждый ведущий несет ответственность за представление одного представления. Единственный способ, которым презентатор может представить несколько представлений, состоит в том, что разные представления представляют собой просто разные реализации одного интерфейса представления, который связывается с ведущим. – Ari

+0

@ Ари благодарю вас за продолжение - это действительно имеет смысл! – AgentKnopf

ответ

12

Деятельность/фрагменты следует рассматривать как просто представление в модели MVP. Это означает, что они должны просто показывать данные и получать пользовательские взаимодействия. Вполне нормально передавать активность и фрагменты через интерфейс/обратные вызовы.

Но это не ответственность за действие/фрагмент, чтобы вызвать службы API.

Ведущий должен нести ответственность за вызов служб api.

Итак, ведущий должен выставить такой метод, как loadXXX, внутренне он сделает звонок к сервису. Когда ответ получен, ведущий должен позвонить view.showXXX с результатами этой услуги. Действие/фрагмент должен вызвать этот метод loadXXX и реализовать showXXX.

Обычно презентатор создается или вводится в действие/фрагмент. Действие/фрагмент должен реализовывать интерфейс, открытый презентатором, а ведущий хранит слабую ссылку на этот интерфейс, чтобы он мог обратный вызов.

Когда пользователь взаимодействует с экраном, например, onClick на кнопке, действие/фрагмент вызывает соответствующий метод в презентаторе, например. presenter.loadUserDetails() Ведущий сообщает, что представление отображается как загрузка, например. view.showAsLoading(), потому что он должен делать свои вещи: возможно, что-то подтвердить или загрузить данные из службы api и, наконец, обратный вызов с результатами в представление, например. view.showUserDetails(userDetails).

Резюмируя, пример, в коде различных частей MVP:

Деятельность/Фрагмент представляет собой лишь Вид MVP:

public class MyActivity extends AppCompatActivity implements MyPresenter.View { 
    private MyPresenter mPresenter; 

    public onCreate() { 
     ... 
     mPresenter = new MyPresenter(this); // Or inject it and then set the view. 
    } 

    public void onClick(View v) { 
     mPresenter.loadXXX(param1, param2); 
    } 

    // MyPresenter.View methods 

    public void showAsLoading() { 
     ... 
    } 

    public void showUserDetails(UserDetails userDetails) { 
     ... 
    } 
} 

Модель:

public class UserDetails { 
    ... 
} 

Presenter :

public class MyPresenter { 

    private WeakReference<MyPresenter.View> mWeakView; 

    public MyPresenter(MyPresenter.View view) { 
     mWeakView = new WeakReference(view); 
    } 

    public void loadXXX(String param1, String param2) { 
     MyPresenter.View view = mWeakView.get(); 
     if (view != null) { 
      view.showAsLoading(); 
      // Do stuff, e.g. make the Api call and finally call view.showUserDetails(userDetails); 
     } 
    } 

    interface View { 
     void showAsLoading(); 
     void showUserDetails(UserDetails userDetails); 
    } 

} 
+0

сэр, не могли бы вы объяснить, почему mWeakView - это WeakReference, по каким причинам? –

+1

Это делается для того, чтобы не сохранять ссылку на Activity/Fragment. Ведущий делает асинхронные запросы к API. Если вы нажмете назад или завершите действие, пока ведущий делает запрос, и вы не используете WeakReference, презентатор сохранит память Activity/Fragment (сохраняя все представления и члены этого Activity/Fragment). Вместо использования WeakReference также широко распространено использование метода прикрепления и отсоединения в презентаторе. После создания экземпляра ведущего вы должны вызвать метод attach и когда вызывается функция OnDestroy Activity/Fragment, вы должны вызвать detach. – fernandospr

+0

Если вы не используете метод WeakReference или app/dettach, а ваша активность/фрагмент был уничтожен до того, как запрос ведущего завершился, вы также можете столкнуться с проблемами при завершении запроса, поскольку он попытается что-то обновить на уничтоженном деятельность/фрагмент. – fernandospr

Смежные вопросы