It's been two weeks since Droidcon NYC 2016 happened. I attended last year's event, and continue to be impressed by the high-quality speakers and talks this conference attracts. All talks were recorded by SlidesLive and will be available in a few weeks.
Here's a rundown of the sessions I attended on Day 1. (I also wrote about Day 2.)
Coldstart: Why Should You Care and How?
Vikram Bodicherla (@vikramb0), an Android developer from Yahoo!, spoke about continual analysis and optimization of app startup time. He defined an app as being started, when a user sees "something useful" on screen, i.e. fresh data is being presented. The goal is to get to this state in under two seconds.
At Yahoo!, they've developed a framework that can be used to measure what contributes to app startup time, visualize a timeline of events to see what is happening, and, record these numbers continually so that regressions are automatically flagged. I was hoping he'd end by saying that Yahoo! has open-sourced this framework, but no such luck.
For more thoughts on app startup, the NimbleDroid blog has published a number of articles on the subject this year.
Supercharging Your Android Release with Fastlane
Andrea Falcone (@asfalcone) is a developer at Twitter, and has worked on Crashlytics and Fabric. She led with a great hook: how to get two hours of your time back every week. Her talk described fastlane, a suite of automation tools for mobile development.
- Automating Beta Deployment
Every time you want to publish an internal build of your app, you need to bump the version number, create a tag, compile a release version, upload the binary, edit the release notes, then announce it. There are a number of fastlane actions that can be used to automate these tasks.
- Automating Screenshot Generation
Capturing screenshots manually in Android is cumbersome and prone to error. screengrab tries to solve this problem by letting you programmatically generate screenshots, as part of an Espresso test. It can even automate switching locales for you.
- Automating Dev Console Publishing
Finally, supply lets you work with the Google Play Store programmatically. It allows you to script updates to your app's metadata, screenshots and binaries. Actions like uploading APKs, editing release notes, or refreshing screens can all be automated. One awesome feature it has, is pulling down your existing Play Store listing, so you can start managing it in version control.
Gradle Update 2016
Hans Dockter (@hans_d) gave an update of new and upcoming features in Gradle.
- Composite Builds: Suppose your project uses a library by specifying an artifact as a dependency. If the library exists in a separate repository, and you make a change to the library, you have to publish the new artifact to a local repository, then update your project to use that build. As of Gradle 3.1, the new composite build feature aims to streamline this workflow.
- Gradle Script Kotlin: This language from JetBrains has rich features (static typing, extension functions) that make it suitable for writing Gradle build scripts. IDE support (in both IDEA and Eclipse) means you'll be able to get auto-completion, refactoring, and other nice things. Ed.: Another reason for me to start looking at Kotlin!
- Local Machine and Distributed Cache Currently, Gradle caches outputs locally per build, but there is now experimental support for caching outputs across all builds (e.g. across branches) on a machine. The logical extension of this is a cloud-based cache, so that build outputs could be shared across different machines. Imagine your fleet of continuous integration machines compiling all of your library dependencies, then making those available to you immediately! The Gradle team thinks the caching features will be ready by end of Q4, though you can try out the local machine caching now with
- Performance: There were huge improvements made between from Gradle 2.14 to 3.1, so upgrade if you can. Also, enabling Dex In Process can improve builds and Instant Run performance.
- Build Scans are reports about your builds that are stored in the cloud (or, on premise, via Gradle Enterprise). They display build failures, compute time spent performing various tasks, let you search logs, and capture analytics.
Keynote: Android is for everyone
One billion people have some kind of disability, and nearly everyone will experience some kind of temporary disability during their lifetime. Ed. I tore my Achilles last year and experienced first-hand the challenges of getting around with a handicap.
Some resources for making Android apps more accessible that Kelly shared:
- Set the
android:accessibilityTraversalBeforeattribute on Floating Action Buttons, so that they are "seen" by screen readers before a long list. More on that here.
- Voice Access is an accessibility service app from Google, that allows people to navigate an Android device with their voice. Another Google app is Accessibility Scanner which can audit any app for accessibility issues.
- Set a value for
contentDescriptionon buttons and images, for use by screen readers. Non-button clickable views should include a button suffix in their descriptions, so vision-impaired users know the view can be tapped.
For a carousel, you can just put a horizontal
LinearLayoutManager item inside a vertical list and it will just work. For snapping to a particular item, use the Support 24.1's
SnapHelper, and refer to this sample project. A ViewPager can be simulated using
LinearSnapHelper and making page widths
The swipe-to-delete pattern is made easy via
ItemTouchHelper. (Paul Burke has a good article about this.) You can even override
onChildDraw() to change the appearance of the item as it's being swiped.
As of 24.2.0, the RecyclerView package now includes
DiffUtil which efficiently computes the difference between two lists, so that you can issue specific update operations on your adapter.
For dealing with multiple view types in lists, instead of naively switching on integer view types, Lisa outlined using a base item type that defines the layout and binding logic. This approach has been open-sourced in a library from Airbnb called Epoxy. (Danny Preussler also wrote an article recently describing an approach using the Visitor pattern.)
Next, she turned to implementing multiple columns, which, for most cases,
GridLayoutManager can be used. For layouts where items can have different spans, you need to implement a lookup method.
Grouping is another tricky area, especially when you can have rows loaded dynamically as a result of expanding a row. A project Lisa open-sourced called Groupie attempts to simplify working with grouped items in RecyclerView.
Finally, the presentation ended with a few tips about using
ItemDecoration to implement spacing around columns. The case of evenly spaced ones is straightforward, but if you need to mix full bleed and edge-padded items in the same RecyclerView, you'll need a bit more logic. The
DebugItemDecoration class can be useful for figuring out layout issues.
Expandable RecyclerView and You
Amanda Hill (@mandybess) presented her implementation of a RecyclerView that handles expanding rows. She pointed out that Android doesn't offer one (despite the existence of ExpandableListView), and while there were implementations out there, e.g. from Big Nerd Ranch, none of them did what she wanted.
She began by having us think about an expandable dataset as one that had two dimensions, and extending RecyclerView to be able to show data elements in both dimensions. Her implementation was clean and straightforward, employing a class to define a group of items, separate view holders for the groups and children, and an adapter that knows about grouping. There were even extensions to allow for multiple view types in either the group or children, as well as items that are checkable.
This presentation was heavy on code samples, but I never felt lost, and Amanda used emoji and audience quizzes to keep us engaged. I chatted briefly with her afterwards about how this might work with a CursorAdapter, as that is usually the data source for RecyclerView in my apps. Something to look into for later…
Testable Android Architecture
Chuck Greb (@ecgreb) talked about how to architect Android apps to allow better testing.
Android has no shortage of testing frameworks, nor adaptations of software patterns for architecting apps. But with the complexity of Activity lifecycle, Fragment interaction, background tasks, network calls, etc. it can be hard to come up with a sane way to structure and test an app.
Chuck first described existing systems such as MVC, MVP and MVVM and how they weren't well-matched with how Android activities work. His proposed solution is named MVPC (Model-View-Presenter-Controller). It explicitly separates an app into a Model (for data), a View, a Controller (an Activity, dealing with lifecycle events and system services) and a Presenter (for logic). Only the Activity and View deal with Android-specific stuff; the Presenter and Model are pure Java.
He ended by talking about what makes a unit test, referring us to an old article by Michael Feathers that defines a set of unit testing rules.
Ed. I've applied MVP on my current app recently, and am very interested in hearing different perspectives on applying it for Android.
Play Services Tasks API
The goal of this API is to provide a unified (throughout Play Services), straightforward interface to deal with tasks (asynchronous method calls). Doug went over how to run tasks in serial, parallel and synchronously, as well as a number of the built-in classes that can be customized. As Firebase makes liberal use of Task objects, you'll definitely encounter them when working with that set of services.
For more information, Doug wrote a multi-part series recently on the Task API.
A Journey Through MV Wonderland
Florina Muntenescu (@FMuntenescu) surveyed the various architectural patterns in common use for Android apps, comparing their advantages and disadvantages. As I've been exploring MVP recently, this talk was perfectly aligned with my current interests.
MVC on Android suffers from the problem that the Activity is typically acting as both the View and the Controller. The View also knows about both the Model and Controller. If we break the link between View and Model, we find ourselves with MVP. The typical implementation defines contract interfaces for the View and Presenter. The latter is easily tested, because the Model and View can be easily mocked and passed in. Finally, Florina described MVVM, where the Presenter is replaced by a ViewModel, which exposes a state of the View, and not individual attributes.
A major benefit of using MVP or MVVM is that UI and other business logic can be easily tested, because they live in plain Java classes, and not Android ones (like an Activity or Fragment). Her sample repository compares MVP and MVVM. She also contributed to the Android Architecture Blueprints, a resource which I have been studying intensely.
Other Trip Reports
- Victor Nascimento wrote up his experience
- Florina herself wrote a report
- Tom Wilson attended many of the same talks I did, and wrote up his report here
Read my thoughts on Day 2 here