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

Android Forestry (Droidcon NYC 2015)

Android Forestry (Droidcon NYC 2015)

An Android app is a forest of trees: views, contexts, navigation, and model. These hierarchical structures are distinct but often entangled, making apps complex, hard to build, and harder to understand.

This talk focuses on how Square has cleared the forest, teasing the trees apart to build simple, testable, maintainable apps. It covers the techniques we use to work with each tree individually and to manage their interactions to minimize complexity.

Logan Johnson

August 28, 2015
Tweet

Other Decks in Programming

Transcript

  1. java.lang.StackOverflowError at android.text.SpannedString.getSpans(SpannedString.java:25) at android.text.TextLine$SpanSet.init(TextLine.java:878) at android.text.TextLine.handleRun(TextLine.java:976) at android.text.TextLine.drawRun(TextLine.java:397) at

    android.text.TextLine.draw(TextLine.java:195) at android.text.Layout.draw(Layout.java:425) at android.text.BoringLayout.draw(BoringLayout.java:400) at android.widget.TextView.onDraw(TextView.java:5255) at android.view.View.draw(View.java:11227) at android.view.View.getDisplayList(View.java:10666) at android.view.ViewGroup.drawChild(ViewGroup.java:2858)
  2. java.lang.StackOverflowError at android.text.SpannedString.getSpans(SpannedString.java:25) at android.text.TextLine$SpanSet.init(TextLine.java:878) at android.text.TextLine.handleRun(TextLine.java:976) at android.text.TextLine.drawRun(TextLine.java:397) at

    android.text.TextLine.draw(TextLine.java:195) at android.text.Layout.draw(Layout.java:425) at android.text.BoringLayout.draw(BoringLayout.java:400) at android.widget.TextView.onDraw(TextView.java:5255) at android.view.View.draw(View.java:11227) at android.view.View.getDisplayList(View.java:10666) at android.view.ViewGroup.drawChild(ViewGroup.java:2858) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2497)
  3. public final class MyApp extends Application {
 
 public static

    User getUser() { ... } public static Database getDatabase() { ... } 
 public static Server getServer() { ... } public static SellerInfo getSeller() { ... }
 
 public static Items getItems() { ... }
 
 public static Settings getSettings() { ... }
 }
  4. class ContextWrapper extends Context {
 ContextWrapper(Context base) { ... }


    
 Object getSystemService(String name) {
 return mBase.getSystemService(name);
 } }
  5. class { public final Context getContext() { ... } }

    class Activity extends ContextThemeWrapper
  6. class View { public final Context getContext() { ... }

    } class Application extends ContextWrapper class Activity extends ContextThemeWrapper
  7. class View { public final Context getContext() { ... }

    } class Application extends ContextWrapper class Activity extends ContextThemeWrapper class Service extends ContextWrapper
  8. class View { public final Context getContext() { ... }

    } class Application extends ContextWrapper class Activity extends ContextThemeWrapper class Service extends ContextWrapper class Application class Activity class View
  9. class } class Application extends ContextWrapper class Activity extends ContextThemeWrapper

    class Service extends ContextWrapper class View { public final Context getContext() { ... } }
  10. class Home extends Screen 
 class Settings extends Screen class

    ItemList extends Screen
 class Item extends Screen {
 final String itemId; // e.g. “bagel”
 }
  11. class Home extends Screen 
 class Settings extends Screen class

    ItemList extends Screen
 class Item extends Screen {
 final String itemId; // e.g. “bagel”
 } class Item extends Screen {
 final String itemId; // e.g. “bagel”
 }
  12. Object module = getDaggerModule(screen); ObjectGraph baseGraph = base.getSystemService(DAGGER); ObjectGraph screenGraph

    = baseGraph.plus(module); return new ScreenContextWrapper(base, screenGraph); Context createContext(Context base, Screen screen) { }
  13. Object module = getDaggerModule(screen); ObjectGraph baseGraph = base.getSystemService(DAGGER); ObjectGraph screenGraph

    = baseGraph.plus(module); return new ScreenContextWrapper(base, screenGraph); Context createContext(Context base, Screen screen) { }
  14. Object module = getDaggerModule(screen); ObjectGraph baseGraph = base.getSystemService(DAGGER); ObjectGraph screenGraph

    = baseGraph.plus(module); return new ScreenContextWrapper(base, screenGraph); Context createContext(Context base, Screen screen) { }
  15. Object module = getDaggerModule(screen); ObjectGraph baseGraph = base.getSystemService(DAGGER); ObjectGraph screenGraph

    = baseGraph.plus(module); return new ScreenContextWrapper(base, screenGraph); Context createContext(Context base, Screen screen) { }
  16. Object module = getDaggerModule(screen); ObjectGraph baseGraph = base.getSystemService(DAGGER); ObjectGraph screenGraph

    = baseGraph.plus(module); return new ScreenContextWrapper(base, screenGraph); Context createContext(Context base, Screen screen) { }
  17. java.lang.StackOverflowError at android.text.SpannedString.getSpans(SpannedString.java:25) at android.text.TextLine$SpanSet.init(TextLine.java:878) at android.text.TextLine.handleRun(TextLine.java:976) at android.text.TextLine.drawRun(TextLine.java:397) at

    android.text.TextLine.draw(TextLine.java:195) at android.text.Layout.draw(Layout.java:425) at android.text.BoringLayout.draw(BoringLayout.java:400) at android.widget.TextView.onDraw(TextView.java:5255) at android.view.View.draw(View.java:11227) at android.view.View.getDisplayList(View.java:10666) at android.view.ViewGroup.drawChild(ViewGroup.java:2858) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2497)
  18. class Seller extends Screen class Items extends Seller class Item

    extends Items {
 final String itemId; // e.g. “bagel”
 }
  19. class Seller extends Screen class Items extends Seller class Item

    extends Items {
 final String itemId; // e.g. “bagel”
 } Seller extends Screen Items extends Seller Item extends Items
  20. class Item extends Path {
 final String itemId; // e.g.

    “bagel”
 
 @Override Path buildAbsolute(Builder abs) {
 return Path.root() .append(new Seller()) .append(new Items()) .append(this);
 }
 }