Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

My way to clean android v2 English DroidCon Spain

1.595 visualizaciones

Publicado el

My way to clean Android v2 English. Droidcon Spain

Publicado en: Tecnología
  • Sé el primero en comentar

My way to clean android v2 English DroidCon Spain

  1. 1. My way to clean Android v2 Christian Panadero http://panavtec.me @PaNaVTEC Github - PaNaVTEC My Way to clean Android V2
  2. 2. My way to clean Android v2 Acknowledgements Fernando Cejas Jorge Barroso Pedro Gomez Sergio Rodrigo @fernando_cejas @flipper83 @pedro_g_s @srodrigoDev Android developer @ Sound CloudAndroid developer @ Karumi Cofounder & Android expert @ Karumi Android developer @ Develapps Alberto Moraga Carlos Morera @albertomoraga @CarlosMChica iOS Developer @ Selltag Android Developer @ Viagogo
  3. 3. My way to clean Android v2 “My way to clean Android”
  4. 4. My way to clean Android v2 • Independent of Frameworks • Testable • Independent of UI • Independent of Database • Independent of any external agency Why clean architecture?
  5. 5. My way to clean Android v2 • Command pattern (Invoker, command, receiver) • Decorator Pattern • Interactors / Use cases • Abstractions • Data Source • Repository • Annotation Processor Concepts
  6. 6. My way to clean Android v2 Abstraction levels Presenters Interactors Entities Repository Data sources UI Abstractions
  7. 7. My way to clean Android v2 The dependency rule Presenters Interactors Entities Repository Data sources UI Abstractions
  8. 8. My way to clean Android v2 • App (UI, DI and implementation details) • Presentation • Domain y Entities • Repository • Data Sources Thinking in projects
  9. 9. My way to clean Android v2 Project dependencies App Presenters Domain Data Entities Repository
  10. 10. My way to clean Android v2 Flow View Presenter Presenter Interactor Interactor Interactor Interactor Repository Repository DataSource DataSource DataSource
  11. 11. My way to clean Android v2 UI: MVP ViewPresenter(s) Model Events Fill the view Actions Actions output
  12. 12. My way to clean Android v2 UI: MVP - View public class MainActivity extends BaseActivity implements MainView { 
 @Inject MainPresenter presenter;
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 presenter.attachView(this);
 } 
 @Override protected void onResume() {
 super.onResume();
 presenter.onResume();
 }
 
 @Override public void onRefresh() {
 presenter.onRefresh();
 }
 
 }
  13. 13. My way to clean Android v2 UI: MVP - Presenter public class MainPresenter extends Presenter<MainView> { public void onResume() {
 refreshContactList();
 }
 
 public void onRefresh() {
 getView().refreshUi();
 refreshContactList();
 } }
  14. 14. My way to clean Android v2 UI: MVP - Presenter @ThreadDecoratedView
 public interface MainView extends PresenterView {
 void showGetContactsError();
 
 void refreshContactsList(List<PresentationContact> contacts);
 
 void refreshUi();
 } public interface PresenterView {
 void initUi();
 } prevents spoiler :D
  15. 15. My way to clean Android v2 • The configuration change is located in UI module, so solve it in this module • configurationChange create a new Activity instance • onRetainCustomNonConfigurationInstance to the rescue! • Retain the DI graph onConfigurationChange Hell
  16. 16. My way to clean Android v2 onConfigurationChange Hell public abstract class BaseActivity extends ActionBarActivity {
 @Override protected void onCreate(Bundle savedInstanceState) {
 createActivityModule();
 } 
 private void createActivityModule() {
 activityInjector = (ActivityInjector) getLastCustomNonConfigurationInstance();
 if (activityInjector == null) {
 activityInjector = new ActivityInjector();
 activityInjector.createGraph(this, newDiModule());
 }
 activityInjector.inject(this);
 }
 
 @Override public Object onRetainCustomNonConfigurationInstance() {
 return activityInjector;
 }
 
 protected abstract Object newDiModule();
 }
  17. 17. My way to clean Android v2 Presentation - Domain (ASYNC) Presenter Invoker Interactor Output Invoker IMP Interactor
  18. 18. My way to clean Android v2 Presentation - Domain (SYNC) Presenter Invoker Future Invoker IMP Interactor .get();.cancel();
  19. 19. My way to clean Android v2 Presentation - Domain public class MainPresenter extends Presenter<MainView> { @Output InteractorOutput<List<Contact>, RetrieveContactsException> output;
 public MainPresenter(…) {
 InteractorOutputInjector.inject(this);
 } public void onResume() {
 interactorInvoker.execute(getContactsInteractor, output);
 } @OnError void onContactsInteractorError(RetrieveContactsException data) {
 getView().showGetContactsError();
 } @OnResult void onContactsInteractor(List<Contact> result) {
 List<PresentationContact> presentationContacts = listMapper.modelToData(result);
 getView().refreshContactsList(presentationContacts);
 } }
  20. 20. My way to clean Android v2 Domain - Interactor public class GetContactInteractor implements Interactor<Contact, ObtainContactException> {
 
 private ContactsRepository repository;
 private String contactMd5;
 
 public GetContactInteractor(ContactsRepository repository) {
 this.repository = repository;
 }
 
 public void setData(String contactMd5) {
 this.contactMd5 = contactMd5;
 }
 
 @Override public Contact call() throws ObtainContactException {
 return repository.obtain(contactMd5);
 }
 }
  21. 21. My way to clean Android v2 Bye bye thread Hell! public class DecoratedMainView implements MainView { @Override public void showGetContactsError() {
 this.threadSpec.execute(new Runnable() {
 @Override public void run() {
 undecoratedView.showGetContactsError();
 }
 });
 } }
  22. 22. My way to clean Android v2 Bye bye thread Hell! public abstract class Presenter<V extends PresenterView> {
 private V view;
 private ThreadSpec mainThreadSpec;
 
 public Presenter(ThreadSpec mainThreadSpec) {
 this.mainThreadSpec = mainThreadSpec;
 }
 
 public void attachView(V view) {
 this.view = ViewInjector.inject(view, mainThreadSpec);
 }
 
 public void detachView() {
 view = null;
 }
 
 public V getView() {
 return view;
 }
 }
  23. 23. My way to clean Android v2 Bye bye thread Hell! public class MainThreadSpec implements ThreadSpec {
 
 Handler handler = new Handler();
 
 @Override public void execute(Runnable action) {
 handler.post(action);
 }
 } public abstract class Presenter<V extends PresenterView> { public void attachView(V view) {
 this.view = ViewInjector.inject(view, mainThreadSpec);
 } } @ThreadDecoratedView
 public interface MainView extends PresenterView { … }
  24. 24. My way to clean Android v2 Repository Network Data Source BDD Data Source Repository Model Data
  25. 25. My way to clean Android v2 Repository Interface public interface ContactsRepository { 
 List<Contact> obtainContacts() throws RetrieveContactsException;
 
 Contact obtain(String md5) throws ObtainContactException; 
 }
  26. 26. My way to clean Android v2 Repository imp @Override public List<Contact> obtainContacts() throws RetrieveContactsException {
 List<Contact> contacts = null;
 try {
 contacts = bddDataSource.obtainContacts();
 } catch (ObtainContactsBddException … ce) {
 try {
 contacts = networkDataSource.obtainContacts();
 bddDataSource.persist(contacts);
 } catch (UnknownObtainContactsException … ue) {
 throw new RetrieveContactsException();
 } catch (PersistContactsBddException … pe) {
 pe.printStackTrace();
 }
 }
 return contacts;
 }
  27. 27. My way to clean Android v2 Data source Model Data source Imp Data source Mapper
  28. 28. My way to clean Android v2 Data source Interface public interface ContactsNetworkDataSource {
 
 public List<Contact> obtainContacts() throws ContactsNetworkException …; 
 }
  29. 29. My way to clean Android v2 Data source imp private ContactsApiService apiService;
 private static final Transformer transformer = new Transformer.Builder().build(ApiContact.class); @Override public List<Contact> obtainContacts() throws ContactsNetworkException {
 try {
 ApiContactsResponse response = apiService.obtainUsers(100);
 List<ApiContactResult> results = response.getResults();
 List<Contact> contacts = new ArrayList<>();
 
 for (ApiContactResult apiContact : results) {
 contacts.add(transform(apiContact.getUser(), Contact.class));
 }
 
 return contacts;
 } catch (Throwable e) {
 throw new ContactsNetworkException();
 }
 }
  30. 30. My way to clean Android v2 Caching Strategy public interface CachingStrategy<T> {
 boolean isValid(T data);
 } public class TtlCachingStrategy<T extends TtlCachingObject> implements CachingStrategy<T> {
 
 private final long ttlMillis;
 
 @Override public boolean isValid(T data) {
 return (data.getPersistedTime() + ttlMillis) > System.currentTimeMillis();
 }
 
 }
  31. 31. My way to clean Android v2 Caching Strategy @Override public List<Contact> obtainContacts()
 throws ObtainContactsBddException … {
 try {
 List<BddContact> bddContacts = daoContacts.queryForAll();
 if (!cachingStrategy.isValid(bddContacts)) {
 deleteBddContacts(bddContacts);
 throw new InvalidCacheException();
 }
 ArrayList<Contact> contacts = new ArrayList<>();
 for (BddContact bddContact : bddContacts) {
 contacts.add(transform(bddContact, Contact.class));
 }
 return contacts;
 } catch (java.sql.SQLException e) {
 throw new ObtainContactsBddException();
 } catch (Throwable e) {
 throw new UnknownObtainContactsException();
 }
 }
  32. 32. My way to clean Android v2 • Bussines logic doesn’t know where the data came from • It’s easy to change data source implementation • If you change the data sources implementation the business logic is not altered Repository adavantages
  33. 33. My way to clean Android v2 – Uncle Bob “Make implementation details swappable”
  34. 34. My way to clean Android v2 Picasso public interface ImageLoader {
 public void load(String url, ImageView imageView);
 public void loadCircular(String url, ImageView imageView);
 } public class PicassoImageLoader implements ImageLoader {
 private Picasso picasso;
 
 @Override public void load(String url, ImageView imageView) {
 picasso.load(url).into(imageView);
 }
 
 @Override public void loadCircular(String url, ImageView imageView) {
 picasso.load(url).transform(new CircleTransform()).into(imageView);
 }
 }
  35. 35. My way to clean Android v2 ErrorManager public interface ErrorManager {
 public void showError(String error);
 } public class SnackbarErrorManagerImp implements ErrorManager { @Override public void showError(String error) {
 SnackbarManager.show(Snackbar.with(activity).text(error));
 } } public class ToastErrorManagerImp implements ErrorManager {
 @Override public void showError(String error) {
 Toast.makeText(activity, error, Toast.LENGTH_LONG).show();
 }
 }
  36. 36. My way to clean Android v2 • ALWAYS Depend upon abstractions, NEVER depend upon concretions • Use a good naming, if there's a class you've created and the naming does not feel right, most probably it is wrong modeled. • Create new shapes using the initial dartboard to ensure that it's placed on the corresponding layer Tips
  37. 37. My way to clean Android v2 – Uncle Bob “Clean code. The last programming language”
  38. 38. My way to clean Android v2 In Uncle Bob we trust
  39. 39. My way to clean Android v2 https://github.com/PaNaVTEC/Clean-Contacts Show me the code!
  40. 40. My way to clean Android v2 • Fernando Cejas - Clean way • Jorge Barroso - Arquitectura Tuenti • Pedro Gomez - Dependency Injection • Pedro Gomez - Desing patterns • Uncle Bob - The clean architecture • PaNaVTEC - Clean without bus References
  41. 41. My way to clean Android v2 ¿Questions? Christian Panadero http://panavtec.me @PaNaVTEC Github - PaNaVTEC

×