Google I/O 2016: Android notes
- Multitasking – multi-window mode and picture-in-picture mode. This includes the ability to launch window in adjacent activity, and drag and drop between activities.
- Notifications – Custom quick settings tile for an activity
- Multi-locale – users can specify locale beyond their primary locale
- ScopedDirectoryAccess for the shared storage
- New file-level encryption mode (as opposed to block-level encryption) and the corresponding Direct Boot
- Java 8, Jack, and ndk support in Gradle
- GCC deprecated in favor of Clang
TechTalk on Image size/compression
- PNG – Get image down to 256-bit palette (if possible) or compress them using Zopfli. Test the difference with butteraugli
- Convert PNG to Vector drawable using Potrace. Vector drawable are natively supported on Android 5.0 and above. Use compat to use them on the older versions. Or generate PNG for the older versions (not recommended)
- WebP is another option (Note: Speaker failed to mention that WebP is natively supported only on Android).
- Avoid JPEGs. They are usually larger in size.
Techtalk on App size
- Four types of sizes – raw apk size, download size (which includes expansion files), install size (apk size + oat files + extracted .so files), and update size (binary diff)
- Resources.arsc is uncompressed since it has to be memory-mapped – don’t manually compress it. Instead, eliminate the bloat in it using blamer
- Native libraries are uncompressed. To use them without extraction, use “android:extractNativeLibs=false” (6.0+ only)
- Scrape unused configs using resConfigs
- Analyze third-party dependencies using “gradlew app:dependencies"
Techtalk on new App library
- New MessagingStyle notification and NotificationCompat#areNotificationsEnabled
- Faster Chrome custom tabs with preloading in the background
- Dropping support for versions below API 9
- Breaking library into multiple modules (similar to how Google Play services were broken last year)
Techtalk on fragments
- ChildFragment creation was a mess and Google is trying to fix that.
- Don’t use Fragments when a ViewGroup will suffice.
- New FragmentTransaction#commitNow for synchronous commits but without side-effects of executePendingTransactions.
- Fragments allow high-level integration since they automatically plug themselves into activity life-cycles
- Use Activity#onInflate to provide config key etc. to a third-party fragment.
- There were tons of questions related to how to deal with IllegalStateException which happens when a FragmentTransaction is committed after Activity#onSaveInstanceState has been executed. Google’s answer was “it depends on the situation”.
Techtalk on themes and styles
- Themes and styles are both collections of key: value pairs (or key:value-type:value triplet)
- Styles are used for styling a View while Theme is used for setting the theme at the Activity level
- Themes inherit while styles overlay
Techtalk on effectively using Android Studio
The session was filled with effective use of Android Studio. Some useful tips are listed below
- Multi-cursor editing using Cmd + Shift + 8
- Ctrl-shift-<n> for adding bookmark, use ctrl-<n> to jump to that line
- Object.<Cmd-J> to see possible auto-generated code completion options on the Object
- Ctrl-shift-space for smarter auto-completion
- Conditional breakpoints
- C++11 support is available (still experimental)
- adb shell setprop debug.checkjni 1 for JNI debugging
- Setting android.defaultConfig.multiDexEnabled = true in the gradle file will produce legacy multi-dex (which uses DexClassLoader) for API < 21 and modern multi-dex (ART supports loading multiple dex files natively). Incremental legacy multi-dex builds are slower than the modern. Therefore, for faster testing and debugging, add two targets, one <21 and one >= 21, and use the latter for debug builds.
- At least provide 4GB (Xmx4096m) for gradle to run
Android Application architecture for next one Billion users
- In 2000, 25% of 400M users were in the developing world. In 2016, 63% of 3B users are in the developing world.
- 90% of the urban population has at least 3G. 30% of rural population has at least 3G.
- Applications should work in the offline mode. And they should be optimized for bad networks.
- For the offline mode, remove the network from the user flow. Use a local persistent model, all user changes will be synced into this model. And the local model will be synced with the remote model when the network is available. Give feedback to the user on the local model change. Network feedback will always update the local model first and that will be synced to the view.
- Network and non-network tasks should be in different queues. So, if network tasks are pending, they should not block non-network tasks.
- Don’t just translate, localize the app.
- Text-free layouts are more global.
- Fetch lower quality content on 2G (and maybe re-fetch higher quality on 4G)
- Autoplay video only on fast networks. Google ExoPlayer automatically supports that.
- Rather than pre-fetching content using an AlarmManager, use JobScheduler (for API >= 21) or GCMNetworkManager (for older versions).
- Pre-fetching should not fill the internal storage. Warn the user before large pre-fetches.
- Check for the metered network and (deprecated) background data restricted setting.
- Search should work locally in the offline state.
- Auto-retry user’s state-change actions like sending messages. Or at least, show notification on the failure.
- Show “No Internet connected” banner
- Batch network requests
- When returning a photo URL, return its size as well, so, a good placeholder can be displayed till it is downloaded.
- For network-local model interaction, don’t think request-response. Think sync.
- For network-local model interaction, some versioning might be needed to perform the sync.
Techtalk on Recycler View
- ListView was not originally created for the infinite scroll social network streams. Developers started using various undefined features to make it work. That has made it even harder for Google to improve the ListView. Also, the animations are difficult with ListView.
- RecyclerView was created with infinite scroll streams in mind.
- It has a LayoutManager which decides the layout, scrolling, and bringing new items int the focus area.
- It has an Adapter which asks “what changed” not just “something changed”. The adapter creates the View/ViewHolder, binds an item, notifies the RecylerView, handles clicks and takes care of the recovery.
- RecyclerView gets the child from ChildHelper. Use AdapterHelper to synchronize calls to the Adapter.
- RecyclerViewPool pools unused ViewHolders (to avoid memory allocation/deallocation).
- ItemTouchHelper takes care of Drag and Drop.
- ItemDecoration is used for drawing on the RecyclerView canvas.
- ItemAnimator is used for animations when an item is added, removed, changed, or moved.
- Adapter and layout positions are not always in sync. That’s why helpers are important to perform the automatic translation.
Note: I missed a session on Espresso UI testing