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

Cooking up Clean Architecture on Android

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.

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