L'attività/i frammenti devono essere considerati solo la vista nel modello MVP. Ciò significa che dovrebbero solo mostrare i dati e ricevere le interazioni dell'utente. È ok per comunicare attività e frammenti tramite interfaccia/callback.
Tuttavia, non è responsabilità di attività/frammento chiamare i servizi API.
Il relatore dovrebbe essere responsabile di chiamare i servizi API.
Quindi, il presentatore deve esporre un metodo come loadXXX
, internamente farebbe la chiamata al servizio. Quando viene ricevuta la risposta, il presentatore deve chiamare view.showXXX
con i risultati del servizio. L'attività/frammento dovrebbe chiamare questo metodo loadXXX
e implementare il showXXX
.
In genere, il presentatore viene creato o iniettato nell'attività/frammento. L'attività/frammento deve implementare un'interfaccia esposta dal presentatore e il presentatore contiene un riferimento debole di questa interfaccia, in modo che possa richiamare.
Quando l'utente interagisce con lo schermo, ad esempio un onClick
su un pulsante, l'attività/frammento chiama il metodo corrispondente nel presentatore, ad es. presenter.loadUserDetails()
il presentatore indica la vista da mostrare come carico, ad es. view.showAsLoading()
perché deve fare le sue cose: forse convalidare qualcosa o caricare dati da un servizio API e infine richiamare con i risultati alla vista, ad es. view.showUserDetails(userDetails)
.
In sintesi, un esempio, nel codice delle varie parti del MVP:
Attività/Frammento rappresenta solo la vista di 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) {
...
}
}
Modello:
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);
}
}
Solo un pensavo: considererei i frammenti come conteggi (rispetto a MVP), quindi mi chiedo se sarebbe strano avere un relatore che faccia riferimento a più viste (o meglio: i loro callback dell'interfaccia) per visualizzare dati diversi nella vista più appropriata per quello? Penserei che un relatore debba decidere/dirigere quale vista mostra quali dati? Apparentemente più presentatori per una vista è un approccio valido, quindi forse anche il contrario funziona: http://stackoverflow.com/a/2068/1041533 – AgentKnopf
@AgentKnopf in realtà, come indicato qui http://programmers.stackexchange.com/a/261351/206366 in MVP ogni presentatore è responsabile della presentazione di una vista. L'unico modo in cui un relatore può presentare più viste è se le diverse viste sono semplicemente implementazioni diverse di un'interfaccia a vista singola che si lega al presentatore. – Ari
@Ari, grazie per il follow-up, che ha davvero senso! – AgentKnopf