2015-12-13 14 views
33

Ho un'attività con due frammenti in essa.MVP per attività con più frammenti

L'attività (MainActivity) recupera i dati da una API meteo aperta. Ho implementato MVP per questo, in cui: Model contiene tutti gli oggetti di risposta del API
View è il Activity
Presenter contiene MainPresenter, MainPresenterImpl, MainView, GetDataInteractor e GetDataInteractorImpl.

Così, l'attività ottiene i dati dal servizio web. Entrambi i frammenti visualizzeranno i dati dai dati recuperati nell'attività.

Qual è la prassi migliore che utilizza MVP in questa situazione? So come passare i dati tra i frammenti < -> attività tramite interfaccia/callback, la mia domanda è che questo comportamento cambia quando si implementa MVP?

+1

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

+2

@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

+0

@Ari, grazie per il follow-up, che ha davvero senso! – AgentKnopf

risposta

12

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); 
    } 

} 
+0

signore, puoi spiegare perché mWeakView è un WeakReference, per quali ragioni? –

+1

Ciò per evitare di mantenere un riferimento all'attività/frammento. Il presentatore effettua richieste asincrone alle API. Se si preme indietro o si termina l'attività mentre il relatore esegue la richiesta e non si utilizza un WeakReference, il presentatore manterrà la memoria attività/frammento (conservando tutte le viste e i membri di tale attività/frammento). Anziché utilizzare WeakReference, è anche comune esporre un metodo di collegamento e scollegamento nel presentatore. Dopo aver istanziato il presenter, dovresti chiamare il metodo attach e quando viene chiamato ActivityDragony/Fragment, dovresti chiamare detach. – fernandospr

+0

Se non si utilizza un approccio WeakReference né l'approccio attach/dettach e l'attività/frammento è stato distrutto prima che la richiesta del presentatore sia terminata, è possibile che si verifichino dei problemi al termine della richiesta, perché proverà ad aggiornare qualcosa sul server distrutto attività/frammento. – fernandospr

Problemi correlati