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

Tools of the Trade (Droidcon NYC 2015)

Tools of the Trade (Droidcon NYC 2015)

This talk will tour one of the most understated resources in the Android developer arsenal: the support tools.

Learn how to enrich your methods and classes using annotations, so that Lint and Android Studio will be able to spot errors for you. Or use IntelliJ annotations to define contracts, and let the IDE warn you of potential issues before you even run your code once. Take advantage of the tools namespace to bend even the most cryptic XML resource to your will.
----
Since this deck is quite heavy on the animations side, I've exported a video version of it as well, that you can find here: http://youtu.be/z9zyQwyO8l0
----
The talk video is now available here: https://www.youtube.com/watch?v=AeoeD7K8vKI

Sebastiano Poggi

August 28, 2015
Tweet

More Decks by Sebastiano Poggi

Other Decks in Programming

Transcript

  1. TOOLS
    Sebastiano Poggi
    Novoda, Android GDE
    TRADE
    OF THE
    #toolsOfTrade

    View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. 1.3
    Android Studio

    View Slide

  7. “How can this be a NPE?”
    “I wish things were strongly typed,
    all resource IDs look like any other integer!”

    View Slide

  8. “How can this be a NPE?”
    “I wish things were strongly typed,
    all resource IDs look like any other integer!”
    “Why isn’t this text R.color.red?
    It’s showing as black!”

    View Slide

  9. “How can this be a NPE?”
    “I wish things were strongly typed,
    all resource IDs look like any other integer!”
    “Why isn’t this text R.color.red?
    It’s showing as black!”
    “I love Eclipse!”

    View Slide

  10. “How can this be a NPE?”
    “I wish things were strongly typed,
    all resource IDs look like any other integer!”
    “Why isn’t this text R.color.red?
    It’s showing as black!”
    “I love Eclipse!”
    “What? I thought this was on the

    View Slide

  11. “How can this be a NPE?”
    “I wish things were strongly typed,
    all resource IDs look like any other integer!”
    “Why isn’t this text R.color.red?
    It’s showing as black!”
    “I love Eclipse!”
    “What? I thought this was on the
    UI thread, but it’s crashing”

    View Slide

  12. Great news!*

    View Slide

  13. Great news!*

    View Slide

  14. Great news!*
    Annotations and XML attributes
    will save the day

    View Slide

  15. SURPRISE
    QUESTION
    Lint

    View Slide

  16. Lint
    Born in 1979 for C

    View Slide

  17. Lint
    Born in 1979 for C
    Performs static code analysis

    View Slide

  18. Lint
    Born in 1979 for C
    Performs static code analysis
    Should be part of your CI builds

    View Slide

  19. Lint
    Born in 1979 for C
    Performs static code analysis
    Should be part of your CI builds

    View Slide

  20. tools
    xmlns:

    View Slide

  21. tools
    xmlns: namespac

    View Slide

  22. tools
    xmlns: namespace
    Built into the SDK/Android Studio

    View Slide

  23. tools namespace
    Built into the SDK/Android Studio
    Safe to commit under VCS

    View Slide

  24. tools namespace
    Built into the SDK/Android Studio
    Safe to commit under VCS
    (Usually)

    View Slide

  25. tools namespace
    Built into the SDK/Android Studio
    Safe to commit under VCS
    (Usually)

    View Slide

  26. android:layout_width="wrap_content"

    android:layout_height="wrap_content"
    ...
    Design-time overrides
    Override any android attribute
    /> tools:text="Hello world!"

    View Slide

  27. Design-time overrides
    Override any android attribute
    />
    tools:text="Hello world!"
    android:layout_width="wrap_content"

    android:layout_height="wrap_content"
    ...

    View Slide

  28. Tools attributes
    Lint attributes

    View Slide

  29. Tools attributes
    Lint attributes
    Design attributes

    View Slide

  30. Tools attributes
    Lint attributes
    Design attributes

    View Slide

  31. Tools attributes
    Lint attributes
    Design attributes

    View Slide

  32. android:name=".MyApplication"

    android:label="Babou"
    ...
    />
    Should explicitly set allowBackup…
    Lint attribute: ignore
    Similar to @SuppressWarnings

    View Slide

  33. />
    android:name=".MyApplication"

    android:label="Babou"
    ...
    Should explicitly set allowBackup…
    Lint attribute: ignore
    Similar to @SuppressWarnings
    tools:ignore="AllowBackup"

    View Slide

  34. android:name=".MyApplication"

    android:label="Babou"
    ...
    Lint attribute: ignore
    Similar to @SuppressWarnings
    />
    tools:ignore="AllowBackup"
    tools:ignore="AllowBackup"

    View Slide

  35. <br/>...<br/>Lint attribute: targetApi<br/>Equivalent to @TargetApi<br/>/><br/><item android:elevation="8dp"<br/> tools:targetApi="HONEYCOMB"
    android:elevation requires
    API level 21(current min is 19)

    View Slide

  36. <br/>...<br/>Lint attribute: targetApi<br/>Equivalent to @TargetApi<br/>/><br/><item android:elevation="8dp"<br/> tools:targetApi="LOLLIPOP" />
    android:elevation requires
    API level 21(current min is 19)

    View Slide

  37. <br/>...<br/>Lint attribute: targetApi<br/>Equivalent to @TargetApi<br/><item android:elevation="8dp"<br/>
    tools:targetApi="LOLLIPOP" />

    View Slide

  38. Lint attribute: locale
    Helps spell checking
    Helo, I am a typo.

    >
    tools:locale="en">

    View Slide

  39. Lint attribute: locale
    Helps spell checking
    Helo, I am a typo.

    tools:locale="en">

    View Slide

  40. Tools attributes
    Lint attributes
    Design attributes

    View Slide

  41. Design attribute: context
    Helps AS tying a layout to an Activity
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    ...

    >
    tools:context=".map.MapActivity"

    View Slide

  42. Design attribute: context
    Helps AS tying a layout to an Activity
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    ...

    >
    tools:context=".map.MapActivity"

    View Slide

  43. Design attribute: context
    Helps AS tying a layout to an Activity
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    tools:context=".map.MapActivity"
    ...

    >

    View Slide

  44. Design attribute: showIn
    Shows a merge in its parent layout’s include
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    ...

    >
    tools:showIn="@layout/activity_main"

    View Slide

  45. android:layout_width="match_parent"

    android:layout_height="match_parent"
    tools:showIn="@layout/activity_main"
    ...

    >
    Design attribute: showIn
    Shows a merge in its parent layout’s include

    View Slide

  46. Design attribute: menu
    Shows a menu in the layout preview
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    ...

    >
    tools:menu="map"

    View Slide

  47. android:layout_width="match_parent"

    android:layout_height="match_parent"
    tools:menu="map"
    ...

    >
    Design attribute: menu
    Shows a menu in the layout preview

    View Slide

  48. Design attribute: actionBarNavMode
    Shows navigation in the action bar
    android:layout_width="match_parent"

    android:layout_height="match_parent"
    ...

    >
    tools:actionBarNavMode="tabs"

    View Slide

  49. android:layout_width="match_parent"

    android:layout_height="match_parent"
    tools:actionBarNavMode="tabs"
    ...

    >
    Design attribute: actionBarNavMode
    Shows navigation in the action bar …in theory

    View Slide

  50. android:layout_width="match_parent"

    android:layout_height="match_parent"
    Design attribute: layout
    Previews a fragment’s layout
    ...
    />
    tools:layout="@layout/fragment_main"

    View Slide

  51. android:layout_width="match_parent"

    android:layout_height="match_parent"
    tools:layout="@layout/fragment_main"
    ...
    />
    Design attribute: layout
    Previews a fragment’s layout

    View Slide

  52. Design attributes: list*
    Previews a ListView’s items, header and footer
    android:id="@+id/list"

    ...
    tools:listheader="@layout/list_header"

    tools:listitem="@layout/list_item"

    tools:listfooter="@layout/list_footer"
    />

    View Slide

  53. android:id="@+id/list"

    ...
    Design attributes: list*
    Previews a ListView’s items, header and footer
    tools:listheader="@layout/list_header"

    tools:listitem="@layout/list_item"

    tools:listfooter="@layout/list_footer"
    />

    View Slide

  54. Good read
    Tools of the Trade
    by Yours Truly
    https://goo.gl/hZv6S5
    https://goo.gl/sia3ms

    View Slide

  55. Good read
    Tools attributes
    http://goo.gl/lzd6YP

    View Slide

  56. Support annotations
    Require support-annotations dependency

    View Slide

  57. Support annotations
    Require support-annotations dependency
    Design attributes
    support-v4 (and thus v7) depends on it

    View Slide

  58. Support annotations
    Require support-annotations dependency
    support-v4 (and thus v7) depends on it

    View Slide

  59. public static String trim(
    return what.trim();
    Nullability annotations
    @Nullable and @NonNull
    String what) {
    @Nullable
    }

    View Slide

  60. Nullability annotations
    @Nullable and @NonNull
    String what) {
    @Nullable
    public static String trim(
    return what.trim();
    Method invocation may produce
    NullPointerException
    }

    View Slide

  61. public static String trim(
    if (what == null) {

    return "";


    return what.trim();

    Nullability annotations
    @Nullable and @NonNull
    String what) {
    }
    }
    @NonNull

    View Slide

  62. Nullability annotations
    @Nullable and @NonNull
    String what) {
    @NonNull
    }
    }
    public static String trim(
    if (what == null) {

    return "";


    return what.trim();

    Condition 'what == null' is always 'false'

    View Slide

  63. setMainTextColor(R.color.text_color);


    void setMainTextColor(

    textView.setTextColor(getColor(colorId));
    Resource ID annotations
    A lot of @{resType}Res that enforce typing
    @Nullable
    Should pass resolved color instead of resource ID
    }
    int colorId) {

    View Slide

  64. setMainTextColor(R.color.text_color);


    void setMainTextColor(

    textView.setTextColor(getColor(colorId));
    Resource ID annotations
    A lot of @{resType}Res that enforce typing
    @Nullable
    int colorId) {
    }
    @ColorRes

    View Slide

  65. Resource ID annotations
    @AnimatorRes
    @AnimRes
    @AnyRes
    @ArrayRes
    @AttrRes
    @BoolRes
    @ColorRes
    @DimenRes
    @DrawableRes
    @FractionRes
    @IdRes
    @IntegerRes
    @InterpolatorRes
    @LayoutRes
    @MenuRes
    @PluralsRes
    @RawRes
    @StringRes
    @StyleableRes
    @StyleRes
    @XmlRes

    View Slide

  66. setTextColor(R.color.text_color);


    private void setTextColor(

    ...
    RGB Color annotation
    @ColorInt requires color value, not ID
    }
    int color) {
    @ColorInt

    View Slide

  67. setTextColor(R.color.text_color);


    private void setTextColor(

    ...
    RGB Color annotation
    @ColorInt requires color value, not ID
    }
    @ColorInt int color) {
    Should pass resolved color instead
    of resource id here

    View Slide

  68. setValue(20);

    void setValue(

    // Value must be in [0, 10]
    Range annotations
    @FloatRange and @IntRange
    }
    int value) {
    @IntRange(from=0, to=10)

    View Slide

  69. setValue(20);

    void setValue(

    // Value must be in [0, 10]
    Range annotations
    @FloatRange and @IntRange
    }
    int value) {
    @IntRange(from=0, to=10)
    Value must be ≥ 0 and ≤ 10 (was 20)

    View Slide

  70. Range annotations
    setCoords(new int[]{42});

    void setCoords(

    // Value must be int[2]
    @Size for arrays, collections and strings
    }
    int[] value) {
    @Size(2)
    Value must be ≥ 0 and ≤ 10 (was 20)

    View Slide

  71. Range annotations
    setCoords(new int[]{42});

    void setCoords(

    // Value must be int[2]
    @Size for arrays, collections and strings
    }
    int[] value) {
    @Size(2)
    Value must be ≥ 0 and ≤ 10 (was 20)
    Size must be exactly 2

    View Slide

  72. int style;
    TypeDef annotations
    The issue with avoiding enums
    @IntRange(from=0, to=10)
    static final int STYLE_MATERIAL = 0;

    static final int STYLE_HOLOYOLO = 1;
    style = 21;

    View Slide

  73. @IntDef(value={STYLE_MATERIAL, STYLE_HOLOYOLO})

    @Retention(RetentionPolicy.SOURCE)

    @interface Style { }
    TypeDef annotations
    @interface definition: @IntDef and @StringDef
    @IntRange(from=0, to=10)
    static final int STYLE_MATERIAL = 0;

    static final int STYLE_HOLOYOLO = 1;

    View Slide

  74. style = 21;
    TypeDef annotations
    @interface usage
    @IntRange(from=0, to=10)
    Must be one of: STYLE_MATERIAL, STYLE_HOLOYOLO
    static final int STYLE_MATERIAL = 0;

    static final int STYLE_HOLOYOLO = 1;
    int style;
    @Style

    View Slide

  75. static final int STYLE_MATERIAL = 0;

    static final int STYLE_HOLOYOLO = 1;
    TypeDef annotations
    @interface usage
    @IntRange(from=0, to=10)
    @Style int style;
    style = 21; Must be one of: STYLE_MATERIAL, STYLE_HOLOYOLO

    View Slide

  76. Threading annotations
    Specify thread “affinity” for methods
    private void test() {

    textView.setText("Oops!");
    @WorkerThread
    }

    View Slide

  77. Threading annotations
    Specify thread “affinity” for methods
    private void test() {

    textView.setText("Oops!");
    @WorkerThread
    Method setText must be called from the
    UI thread, currently inferred thread is
    worker
    }

    View Slide

  78. Threading annotations
    Specify thread “affinity” for methods
    Method setText must be called from the
    UI thread, currently inferred thread is
    worker
    @MainThread
    @BinderThread
    @UiThread
    @WorkerThread

    View Slide

  79. “Architecture” annotations
    Contracts for methods invocation and overriding
    @CallSuper @CheckResult @VisibleForTesting

    View Slide

  80. Permissions annotations
    Specifies calling a method requires a permission
    startBluetoothScan();
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    private void startBluetoothScan() { ... }

    View Slide

  81. Permissions annotations
    Specifies calling a method requires a permission
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    startBluetoothScan();
    private void startBluetoothScan() { ... }
    Missing permissions required by startBluetoothScan:
    android.permission.BLUETOOTH

    View Slide

  82. Proguard annotation
    Specifies a symbol should be kept by Proguard
    @Keep
    private void myMethod() { ... }

    View Slide

  83. Good read
    Improving Code Inspection
    with Annotations
    https://goo.gl/QLyf10

    View Slide

  84. Good read
    Support annotations
    http://goo.gl/3DTImU

    View Slide

  85. A
    &
    Q

    View Slide

  86. View debugging
    BONUS
    ROUND

    View Slide

  87. View debugging
    Built into the SDK since API 1

    View Slide

  88. View debugging
    Built into the SDK since API 1
    ViewDebug

    View Slide

  89. View debugging
    Built into the SDK since API 1
    ViewDebug

    View Slide

  90. public class MyCustomView extends View {

    private int fancyColor;
    Exported view properties
    Use @ExportedProperty
    @Nullable
    public int getFancyColor() {

    return fancyColor;
    }
    @ViewDebug.ExportedProperty

    View Slide

  91. public class MyCustomView extends View {

    private int fancyColor;
    Exported view properties
    Use @ExportedProperty
    @Nullable
    @ViewDebug.ExportedProperty
    public int getFancyColor() {

    return fancyColor;
    }

    View Slide

  92. Exported view properties
    Use @ExportedProperty
    @Nullable
    (

    category = "My category"

    )
    public int getFancyColor() {

    return fancyColor;
    }
    @ViewDebug.ExportedProperty

    View Slide

  93. Good read
    ViewDebug JavaDoc
    http://goo.gl/v54umV

    View Slide

  94. A
    &
    Q
    (for real this time)
    (also, tweet questions @seebrock3r)

    View Slide

  95. Thank you!
    @seebrock3r
    +SebastianoPoggi
    rock3r
    Sebastiano Poggi
    Novoda, Android GDE
    #toolsOfTrade

    View Slide