Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cooking up Clean Architecture on Android

Avatar for Zan Markan Zan Markan
December 17, 2015

Cooking up Clean Architecture on Android

A talk I gave at CodeMotion Tel Aviv 2015. It covers basics of clean MVP-ish architecture on Android, with some code samples.

Avatar for Zan Markan

Zan Markan

December 17, 2015
Tweet

More Decks by Zan Markan

Other Decks in Programming

Transcript

  1. Stuff We’ll Cover • What & Why & Why &

    What • MVP - ingredients • MVP - layer by layer • Tools • RxJava & other goodies
  2. Examples of Architecture • MVC - asp.net MVC, lots of

    web • MVP - VIPER (iOS) • MVVM - .NET, iOS, Databinding (Android), Angular (I think)
  3. What’s Up With That “Clean” Stuff? • Uncle Bob -

    Clean Code • Uncle Bob - Clean Architecture • Martin Fowler… Image: Fernando Cejas - Clean Architecture
  4. Clean vision of UI “A good architecture hangs the UI

    off the side like an appendix. That makes it easy to remove when it gets inflamed.” - Uncle Bob
  5. Clean in the Android World • It won’t blend THAT

    easily! • Everything extends Context • Everything else *requires* Context • “God” object • UI - first design
  6. Model Layer • Does things • Business logic happens here

    • Handles outward facing APIs, persistence, sensors • Wraps com.android.* -
  7. Wrapper - interface LocationWrapper { void requestLocation(…); } class LocationWrapperImpl

    implements LocationWrapper { GoogleApiClient apiClient; @Override void requestLocation(…){ //setup callbacks etc… LocationServices.FusedLocationApi.getLastLocation( apiClient); } }
  8. Presenter Layer • The “glue” between the “M” and the

    “V” • View tells the presenter what happened • Tells the view what to do • goes to model for data
  9. Presenter - Interface • View initialises it - to keep

    reference • Here’s where the memory leaks happen (if you’re not careful) interface BasketPresenter { void initialise(BasketView view); void itemQuantityChanged(BasketItem basketItem); void viewDestroyed(); }
  10. Clean presenter implementation • Model accessed via interactors interface Interactor<T>

    { void performAction<T action>(InteractionCallback<T> actionCallback); } class CleanBasketPresenterImpl implements BasketPresenter { @Override void initialise(BasketView view){ basketView = view; } @Override void itemQuantityChanged(BasketItem basketItem){ updateItemQuantityInteractor.performAction(basketItem); } }
  11. “Clean-ish” presenter implementation • Presenter directly accesses the model •

    + less classes • - more coupling class CleanishBasketPresenterImpl implements BasketPresenter { @Override void initialise(BasketView view){ basketView = view; } @Override void itemQuantityChanged(BasketItem basketItem){ basketAPI.updateItemQuantity(basketItem); } }
  12. View Layer • A view is a View is an

    Activity • Keep the com.android.* here • Tells presenter what action has occurred • Knows how to show data • Handles navigation to other activities
  13. Views and business logic • Just no. • Keep it

    in presenter…. • (if you must)
  14. View - Interface interface BasketView { void showItems(List<BasketItem> basketItems); void

    update(BasketItem basketItem); void proceedToCheckout(); }
  15. “keep the com.android* here” • coupled to the framework •

    face it - unavoidable • hard to test - need for UI testing class BasketActivity extends Activity implements BasketView { BasketPresenter presenter; //code
  16. “tells the presenter what action has occurred” • Delegates on

    onClick, onDestroy, onResume to presenter • Translates android bits to pure java OnClickListener addToBasketListener = new OnClickListener { @Override public void onClick(View v){ presenter.itemQuantityChanged(basketItemWithNewQuantity); } }
  17. “knows how to show it” • Display logic only in

    view • Both view and presenter understand data objects @Override void update(BasketItem basketItem){ basketViewsList.getView(basketItem.id).setData(basketItem); }
  18. “handles navigation to other activities" • Intent creation needs Context

    • Intent dispatch needs (Activity) Context • Can use builder pattern to construct intents (with data) @Override void proceedToCheckout(){ startActivity(CheckoutActivity.buildIntent(this, basketItems)); }
  19. Libraries to make life easier • Retrofit - REST made

    easy • Dagger - dependency injection • ButterKnife - view binding & easier listeners # • Otto / EventBus -
  20. MVP Libraries to make life easier • There are many:

    Mosby, Nucleus, … • Make conventions easier • Handle presenter lifecycle for you
  21. MVP not your cuppa? • MVVM - Model-View-ViewModel (like .NET)

    • Android DataBinding library to the rescue :) • XML galore! • http://developer.android.com/tools/data-binding/guide.html
  22. Sugar, Spice (and something nice) • Testability comes free cheap

    • (half of the thing is core java anyway) • RxJava friendly
  23. Tired of T-Shirt Weather in December? • M&S Digital is

    hiring (in London) • Mobile, backend, frontend, APIs, you name it! • http://www.mandsdigital.com/careers
  24. Links - architecture • Code samples in one uncompilable Gist

    • https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html • https://vimeo.com/43612849 (clean architecture - talk) • http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ • http://antonioleiva.com/mvp-android/ • https://github.com/android10/Android-CleanArchitecture • https://github.com/rallat/EffectiveAndroid • Fragmented Podcast - The Fowler Road to Clean Architecture
  25. Links - Tools • http://square.github.io/retrofit/ - Retrofit • http://square.github.io/dagger/ -

    Dagger 1 • http://google.github.io/dagger/ - Dagger 2 • http://jakewharton.github.io/butterknife/ - Butterknife • http://square.github.io/otto/ - Otto • http://hannesdorfmann.com/mosby/ - Mosby • https://github.com/konmik/nucleus - Nucleus • https://github.com/ReactiveX/RxJava - RxJava • https://github.com/ReactiveX/RxAndroid - RxAndroid