MVP
Una arquitectura limpia
MVC
Activity / Fragment
Tareas en la UI
Consultas a bases de datos
Control de configuración
MVP
Una arquitectura más limpia
(Desde mi humilde punto de vista)
MVP
By example
Interactor
Presenter
ViewModel

Petición de datos
Notificar
Mostrar información
ViewModel
Todos los métodos que afecten a la vista
public interface ArtistSearchView {
void setupList();
void setupAdapter();
void setupSearchInput();
void displayFoundArtists(ArrayList<Artist> artists);
void displayFailedSearch();
void displayNetworkError();
void displayServerError();
}ViewModel
Comunmente implementado por una actividad o fragmento
@Override
public void setupList() {
mArtistResultsList.setLayoutManager(new LinearLayoutManager(CONTEXT));
mArtistResultsList.setAdapter(mResultsAdapter);
}
@Override
public void setupAdapter() {
mResultsAdapter.setOnItemClickListener(mSearchPresenter);
}
@Override
public void setupSearchInput() {
mArtistSearchInput.setQueryListener(mSearchPresenter);
}
@Override
public void onQueyChange(String query){
mPresenter.searchArtists(query);
}
@Override
public void displayFoundArtists(ArrayList<Artist> artists) {
mResultsAdapter.replace(artists);
}
@Override
public void displayFailedSearch() {
Toast.makeText(CONTEXT, R.string.failed_search, Toast.LENGTH_SHORT).show();
}
@Override
public void displayNetworkError() {
Toast.makeText(CONTEXT, R.string.network_error, Toast.LENGTH_SHORT).show();
}
@Override
public void displayServerError() {
Toast.makeText(CONTEXT, R.string.server_error, Toast.LENGTH_SHORT).show();
}Recibe las interacciones del usuario con la vista
Presenter
Es el puente entre la vista y el interactor
Ejecuta los métodos del interactor para obtener datos
Transfiere los datos obtenidos por el interactor a la vista
Presenter
@Override
public void searchArtists(String query) {
searchInteractor.performSearch(query, this);
}
@Override
public void onArtistsFound(ArrayList<Artist> artists) {
searchView.displayFoundArtists(artists);
}
@Override
public void onFailedSearch() {
searchView.displayFailedSearch();
}
@Override
public void onNetworkError(RetrofitError error) {
error.printStackTrace();
searchView.displayNetworkError();
}
@Override
public void onServerError(RetrofitError error) {
error.printStackTrace();
searchView.displayServerError();
}Interactor
Ejecuta llamadas al servidor, bases de datos o preferencias locales
Se establece comunicación con el presentador a través de interfaces o un Bus de eventos
Interactor
@Override
public void performSearch(String query, final ArtistSearchServerCallback callback){
apiService.searchArtist(query, new Callback<ArtistSearchResponse>() {
@Override
public void success(ArtistSearchResponse artistSearchResponse, Response response) {
if(artistSearchResponse.getArtists().isEmpty())
callback.onFailedSearch();
else
callback.onArtistsFound(artistSearchResponse.getArtists());
}
@Override
public void failure(RetrofitError error) {
if (error.getKind() == RetrofitError.Kind.NETWORK)
callback.onNetworkError(error);
else
callback.onServerError(error);
}
});
}MVP
Recapitulando el proceso de busqueda
ViewModel
void setupList()
void setupAdapter()
void setupSearchInput()
------------------------
void onQueryChange(String query);Presenter
void searchArtists(String query)Interactor
void performSearch(String query,
ArtistSearchServerCallback callback);Presenter
void onArtistsFound(ArrayList<Artist> artists)
void onFailedSearch()
void onNetworkError(RetrofitError error)
void onServerError(RetrofitError error)ViewModel
void displayFoundArtists(ArrayList<Artist> artists);
void displayFailedSearch();
void displayNetworkError();
void displayServerError();MVP
Una arquitectura limpia
Dagger 2
Inyección de dependencias
Dagger 2
Dependencias visibles
Interactor
Presenter
ViewModel
Dependency
Dependency
Dagger 2
¿Qué quiere decir dependencia?
public ArtistSearchPresenter(ArtistSearchView view, ArtistSearchInteractor interactor) {
searchView = view;
searchInteractor = interactor;
}Dependencia
Dependencia
Necesitamos de otros objetos para construir un objeto
Dagger 2
¿Cómo lo soluciona Dagger 2?
Module
Component
Clases que crean instancias de los objetos para la inyección de dependencias
Constituyen una API interna a través de la cual obtenemos los objetos que necesitamos para resolver las dependencias
Dagger 2
Ejemplo
SpotifyStreamerComponent
@Modules
SpotifyStreamerModule
InteractorModule
Context getContext();
ArtistSearchInteractor getArtistSearchInteractor();
SpotifyApiService getSpotifyApiService();API
@Provides @Singleton
public Context provideContext()
@Provides @Singleton
public SpotifyApiService provideSpotifyApiService(RestAdapter adapter)@Provides
public ArtistSearchInteractor provideArtistSearchInteractor(SpotifyApiService apiService)@Provides
@Provides
Dagger 2
Un vistazo más de cerca
En nuestro fragmento, necesitamos el presentador
public class ArtistSearchFragment implements ArtistSearchView {
//...
ArtistSearchPresenter mSearchPresenter;
//...
}¿Qué necesitamos para construir este presentador?
public ArtistSearchPresenter(ArtistSearchView view, ArtistSearchInteractor interactor) {
searchView = view;
searchInteractor = interactor;
}Dagger 2
Un vistazo más de cerca
El módulo definirá como construir el presentador
@Module
public class ArtistSearchModule {
private ArtistSearchView view;
//Para construir este modulo necesitamos el ViewModel
public ArtistSearchModule(ArtistSearchView view) {
this.view = view;
}
@Provides
public ArtistSearchView provideView() {
return view;
}
@Provides
public ArtistSearchPresenter providePresenter(ArtistSearchView view, ArtistSearchInteractor interactor) {
return new ArtistSearchPresenter(view, interactor);
}
}Dagger 2
Un vistazo más de cerca
¿Y que se necesita para construir el interactor?
@Module
public class InteractorModule {
@Provides
public ArtistSearchInteractor provideArtistSearchInteractor(SpotifyApiService apiService){
return new ArtistSearchInteractorImpl(apiService);
}
}¿Dónde se encuentra el SpotifyApiService?
@Module
public class SpotifyStreamerModule {
private SpotifyStreamerApp app;
public SpotifyStreamerModule (SpotifyStreamerApp app) {
this.app = app;
}
@Provides @Singleton public Application provideApplication() {
return app;
}
@Provides @Singleton public Context provideContext() {
return app;
}
@Provides @Singleton public RestAdapter provideApiAdapter() {
return SpotifyApiAdapter.getInstance();
}
@Provides @Singleton public SpotifyApiService provideSpotifyApiService(RestAdapter adapter){
return adapter.create(SpotifyApiService.class);
}
}Dagger 2
Un vistazo más de cerca
Finalmente los componentes proveeran las instancias
@ActivityScope
@Component(
//El interactor puede ser proporcionado por este componente
dependencies = SpotifyStreamerComponent.class,
modules = ArtistSearchModule.class
)
public interface ArtistSearchComponent {
ArtistSearchPresenter getPresenter();
}@Singleton
@Component(
modules = {
SpotifyStreamerModule.class,
InteractorModule.class
}
)
public interface SpotifyStreamerComponent {
ArtistSearchInteractor getArtistSearchInteractor();
}Dagger 2
Un vistazo más de cerca
Ya podemos inyectarlo a nuestro fragmento
@Inject
ArtistSearchPresenter mSearchPresenter;
//Este es el método que declara la inyección de las dependencias
protected void setUpComponent() {
DaggerArtistSearchComponent.builder()
.spotifyStreamerComponent(SpotifyStreamerApp.getApp(getActivity()).getComponent())
.artistSearchModule(new ArtistSearchModule(this))
.build()
.inject(this);
}SpotifyStreamerComponent
@Modules
SpotifyStreamerModule
InteractorModule
Context getContext();
ArtistSearchInteractor getArtistSearchInteractor();@Provides @Singleton
public Context provideContext()
@Provides @Singleton
public RestAdapter provideApiAdapter()
@Provides @Singleton
public SpotifyApiService provideSpotifyApiService(RestAdapter adapter)@Provides
public ArtistSearchInteractor provideArtistSearchInteractor(SpotifyApiService apiService)@Provides
@Provides
Dependency
ArtistSearchComponent
void inject(ArtistSearchFragment searchFragment);
ArtistSearchPresenter getPresenter();ArtistSearchModule
@Modules
@Provides
@Provides
public ArtistSearchView provideView()
@Provides
public ArtistSearchPresenter providePresenter(ArtistSearchView view, ArtistSearchInteractor interactor)MVP + Dagger 2
By Petter Hdz
MVP + Dagger 2
- 781