$30 off During Our Annual Pro Sale. View Details »

Dart & Henson - Better Android Intents

Dart & Henson - Better Android Intents

Presented at Andevcon SF 2016, DroidKaigi Tokyo 2017 and Andevcon Washington 2017

Daniel Molinero Reguera

December 01, 2016
Tweet

More Decks by Daniel Molinero Reguera

Other Decks in Programming

Transcript

  1. BETTER ANDROID INTENTS
    DART & HENSON
    https://github.com/f2prateek/dart

    View Slide

  2. ABOUT US
    Senior Android Dev @ Groupon

    ~20 years of Java coding
    OSS: Dart, TP, BoundBox, …
    STEPHANE NICOLAS
    DANIEL MOLINERO REGUERA
    Android Dev @ Groupon

    Turbulence Ninja
    OSS: Dart, TP.
    +stephane
    @D_Lemures

    View Slide

  3. 5IF"OESPJE5FBNJT)JSJOH

    jobs.groupon.com/careers/

    View Slide

  4. INTENTS & EXTRAS
    NAVIGATION LAYER
    DART: CONSUMING INTENTS
    ANNOTATIONS
    BINDING
    SETUP
    HENSON: CREATING INTENTS
    INTENT BUILDERS
    FLUENT API
    ANNOTATIONS
    SETUP
    CONCLUSION
    THE TALK

    View Slide

  5. AN INTENT IS AN ABSTRACT DESCRIPTION OF
    AN OPERATION TO BE PERFORMED
    INTENTS & EXTRAS
    BROADCAST

    RECEIVER
    SERVICE
    ACTIVITY
    from developer.android.com/reference/android/content/Intent.html

    View Slide

  6. AN INTENT IS AN ABSTRACT DESCRIPTION OF
    AN OPERATION TO BE PERFORMED
    INTENTS & EXTRAS
    ACTIVITY
    from developer.android.com/reference/android/content/Intent.html
    INTENT

    View Slide

  7. EXTRAS CAN BE USED TO PROVIDE EXTENDED
    INFORMATION
    INTENTS & EXTRAS
    ACTIVITY
    from developer.android.com/reference/android/content/Intent.html
    INTENT
    EXTRAS

    View Slide

  8. NAVIGATION LAYER
    ACTIVITY 1
    ACTIVITY 4
    ACTIVITY 2
    ALL INTENTS TOGETHER FORM
    THE NAVIGATION LAYER OF AN ANDROID APP
    ACTIVITY 3
    ACTIVITY 5
    ACTIVITY 6

    View Slide

  9. NAVIGATION LAYER
    HOW TO ORGANIZE 

    YOUR NAVIGATION LAYER ?

    View Slide

  10. CONSUMING & CREATING INTENTS
    DEAL LIST 

    ACTIVITY
    DEAL DETAIL 

    ACTIVITY
    CREATING AN
    INTENT
    CONSUMING AN
    INTENT

    View Slide

  11. View Slide

  12. CONSUMING
    INTENTS

    View Slide

  13. DART
    CONSUMING
    INTENTS

    View Slide

  14. DART: CONSUMING INTENTS
    ACTIVITY
    String field1
    int field2
    boolean field3

    View Slide

  15. DART: CONSUMING INTENTS
    ACTIVITY
    String field1
    int field2
    boolean field3
    INTENT

    View Slide

  16. DART: CONSUMING INTENTS
    ACTIVITY
    String field1
    int field2
    boolean field3
    INTENT
    EXTRA 1 value 1
    EXTRA 2 value 2
    EXTRA 3 value 3
    EXTRAS

    View Slide

  17. DART: CONSUMING INTENTS
    public class DealDetailActivity extends Activity {
    public static final String EXTRA_DEAL_ID = "EXTRA_DEAL_ID";
    public static final String EXTRA_SHOW_MAP = "EXTRA_SHOW_MAP";

    private String dealId;
    private boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    dealId = getIntent().getStringExtra(EXTRA_DEAL_ID);
    shouldShowMap = getIntent().getBooleanExtra(EXTRA_SHOW_MAP, false);
    if (dealId == null) {
    throw new IllegalArgumentException("Deal Id is required");
    }
    ...
    }

    View Slide

  18. public class DealDetailActivity extends Activity {
    public static final String EXTRA_DEAL_ID = "EXTRA_DEAL_ID";
    public static final String EXTRA_SHOW_MAP = "EXTRA_SHOW_MAP";

    private String dealId;
    private boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    dealId = getIntent().getStringExtra(EXTRA_DEAL_ID);
    shouldShowMap = getIntent().getBooleanExtra(EXTRA_SHOW_MAP, false);
    if (dealId == null) {
    throw new IllegalArgumentException("Deal Id is required");
    }
    ...
    }
    DART: CONSUMING INTENTS

    View Slide

  19. public class DealDetailActivity extends Activity {
    public static final String EXTRA_DEAL_ID = "EXTRA_DEAL_ID";
    public static final String EXTRA_SHOW_MAP = "EXTRA_SHOW_MAP";

    private String dealId;
    private boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    dealId = getIntent().getStringExtra(EXTRA_DEAL_ID);
    shouldShowMap = getIntent().getBooleanExtra(EXTRA_SHOW_MAP, false);
    if (dealId == null) {
    throw new IllegalArgumentException("Deal Id is required");
    }
    ...
    }
    DART: CONSUMING INTENTS
    BOILERPLATE!!!

    View Slide

  20. DART: ANNOTATIONS
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  21. DART: ANNOTATIONS
    DECLARE REQUIRED AND OPTIONAL FIELDS
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  22. DART: BINDING
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  23. DART: BINDING
    BIND INTENT EXTRAS TO ANNOTATED FIELDS
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  24. ACTIVITY MODEL
    String field1
    int field2
    boolean field3
    DART: BINDING A MODEL

    View Slide

  25. ACTIVITY MODEL
    String field1
    int field2
    boolean field3
    DART: BINDING A MODEL
    SEPARATE EXTRAS AND ACTIVITIES

    View Slide

  26. public class DealDetailModel {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    }
    MODEL:
    public class DealDetailActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(detailModelInstance, this);
    ...
    }
    ACTIVITY:
    DART: BINDING A MODEL

    View Slide

  27. compile ‘com.f2prateek.dart:dart:2.0.1
    provided ‘com.f2prateek.dart:dart-processor:2.0.1
    GRADLE:

    com.f2prateek.dart
    dart
    2.0.1


    com.f2prateek.dart
    dart-processor
    2.0.1
    provided

    MAVEN:
    DART: SETUP

    View Slide

  28. View Slide

  29. CREATING
    INTENTS

    View Slide

  30. HENSON
    CREATING
    INTENTS

    View Slide

  31. public class CentralIntentFactory {
    public Intent newDealDetailActivityIntent(Context context,
    String dealId) {

    return new Intent(context, DealDetailActivity.class)
    .putExtra(EXTRA_DEAL_ID, dealId);

    }


    public Intent newDealDetailActivityIntent(Context context, 

    String dealId, 

    boolean showMap) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, dealId)

    .putExtra(EXTRA_SHOW_MAP, showMap);

    }

    ...

    }

    HENSON: CREATING INTENTS

    View Slide

  32. public class CentralIntentFactory {
    public Intent newDealDetailActivityIntent(Context context,
    String dealId) {

    return new Intent(context, DealDetailActivity.class)
    .putExtra(EXTRA_DEAL_ID, dealId);

    }


    public Intent newDealDetailActivityIntent(Context context, 

    String dealId, 

    boolean showMap) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, dealId)

    .putExtra(EXTRA_SHOW_MAP, showMap);

    }

    ...

    }

    HENSON: CREATING INTENTS
    - MEYER’S OPEN/CLOSED PRINCIPLE
    - BIG BALL OF MUD

    View Slide

  33. public class DealDetailActivity extends Activity {
    ...
    public static Intent getIntent(Context context, 

    String dealId) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, dealId);

    }


    public static Intent getIntent(Context context, 

    String dealId, 

    boolean showMap) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, itemId)

    .putExtra(EXTRA_SHOW_MAP, showMap);

    }
    ...

    }

    HENSON: CREATING INTENTS

    View Slide

  34. public class DealDetailActivity extends Activity {
    ...
    public static Intent getIntent(Context context, 

    String dealId) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, dealId);

    }


    public static Intent getIntent(Context context, 

    String dealId, 

    boolean showMap) {

    return new Intent(context, DealDetailActivity.class)

    .putExtra(EXTRA_DEAL_ID, itemId)

    .putExtra(EXTRA_SHOW_MAP, showMap);

    }
    ...

    }

    HENSON: CREATING INTENTS
    BOILERPLATE!!!

    View Slide


  35. HENSON: INTENT BUILDERS
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  36. DART & HENSON
    GENERATE THEM FOR YOU !

    HENSON: INTENT BUILDERS
    public class DealDetailActivity extends Activity {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(this);
    ...
    }
    }

    View Slide

  37. public class DealDetailActivity$$IntentBuilder {

    private Intent intent;

    private Bundler bundler = Bundler.create();


    public DealDetailActivity$$IntentBuilder(Context context) {

    intent = new Intent(context, DealDetailActivity.class);

    }


    public DealDetailActivity$$IntentBuilder dealId(String dealId) {

    bundler.put("dealId", dealId);

    return this;

    }


    public DealDetailActivity$$IntentBuilder shouldShowMap(Boolean shouldShowMap) {

    bundler.put(“shouldShowMap", shouldShowMap);

    return this;

    }


    public Intent build() {

    intent.putExtras(bundler.get());

    return intent;

    }
    }

    HENSON: INTENT BUILDERS

    View Slide

  38. public class DealDetailActivity$$IntentBuilder {

    private Intent intent;

    private Bundler bundler = Bundler.create();


    public DealDetailActivity$$IntentBuilder(Context context) {

    intent = new Intent(context, DealDetailActivity.class);

    }


    public DealDetailActivity$$IntentBuilder dealId(String dealId) {

    bundler.put("dealId", dealId);

    return this;

    }


    public DealDetailActivity$$IntentBuilder shouldShowMap(Boolean shouldShowMap) {

    bundler.put(“shouldShowMap", shouldShowMap);

    return this;

    }


    public Intent build() {

    intent.putExtras(bundler.get());

    return intent;

    }
    }

    HENSON: INTENT BUILDERS

    View Slide

  39. public class DealDetailActivity$$IntentBuilder {

    private Intent intent;

    private Bundler bundler = Bundler.create();


    public DealDetailActivity$$IntentBuilder(Context context) {

    intent = new Intent(context, DealDetailActivity.class);

    }


    public DealDetailActivity$$IntentBuilder dealId(String dealId) {

    bundler.put("dealId", dealId);

    return this;

    }


    public DealDetailActivity$$IntentBuilder shouldShowMap(Boolean shouldShowMap) {

    bundler.put(“shouldShowMap", shouldShowMap);

    return this;

    }


    public Intent build() {

    intent.putExtras(bundler.get());

    return intent;

    }
    }

    HENSON: INTENT BUILDERS

    View Slide


  40. HENSON: FLUENT API
    Intent intent = Henson.with(context)
    .gotoDealDetailActivity()
    .dealId(dealId)
    .shouldShowMap(true)
    .build();

    View Slide


  41. HENSON: FLUENT API
    Intent intent = Henson.with(context)
    .gotoDealDetailActivity()
    .dealId(dealId)
    .shouldShowMap(true)
    .build();
    HENSON CLASS PROVIDES A FLUENT API
    TO ACCESS INTENT BUILDERS

    View Slide

  42. HENSON: ANNOTATIONS
    @HensonNavigable
    public class SettingsActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    }
    }

    View Slide

  43. HENSON: ANNOTATIONS
    MAKE YOUR ACTIVITIES VISIBLE TO HENSON
    EVEN IF THEY DON'T USE DART ANNOTATIONS
    @HensonNavigable
    public class SettingsActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    }
    }

    View Slide

  44. public class DealDetailModel {

    @InjectExtra String dealId;
    @InjectExtra @Nullable Boolean shouldShowMap;
    }
    MODEL:
    @HensonNavigable(model = DealDetailModel.class)
    public class DealDetailActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Dart.inject(detailModelInstance, this);
    ...
    }
    ACTIVITY:
    HENSON: ANNOTATIONS

    View Slide

  45. compile ‘com.f2prateek.dart:henson:2.0.1
    provided ‘com.f2prateek.dart:henson-processor:2.0.1
    GRADLE:

    com.f2prateek.dart
    henson
    2.0.1


    com.f2prateek.dart
    henson-processor
    2.0.1
    provided

    MAVEN:
    HENSON: SETUP

    View Slide

  46. CONCLUSION
    QUESTIONS ?
    COMMENTS ?

    View Slide

  47. CONCLUSION
    QUESTIONS ?
    COMMENTS ?

    View Slide

  48. BETTER ANDROID INTENTS
    DART & HENSON
    https://github.com/f2prateek/dart
    +stephane
    @D_Lemures

    View Slide