Tareas en la UI
Consultas a bases de datos
Control de configuración
(Desde mi humilde punto de vista)
Interactor
Presenter
ViewModel
Petición de datos
Notificar
Mostrar información
public interface ArtistSearchView {
void setupList();
void setupAdapter();
void setupSearchInput();
void displayFoundArtists(ArrayList<Artist> artists);
void displayFailedSearch();
void displayNetworkError();
void displayServerError();
}
@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();
} @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();
}@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);
}
});
}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();
Interactor
Presenter
ViewModel
Dependency
Dependency
public ArtistSearchPresenter(ArtistSearchView view, ArtistSearchInteractor interactor) {
searchView = view;
searchInteractor = interactor;
}Dependencia
Dependencia
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
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
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;
}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);
}
}¿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);
}
}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();
}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)