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

[Warsaw] Android Jetpack - what you need to know in 2019

[Warsaw] Android Jetpack - what you need to know in 2019

Miłosz Lewandowski

December 07, 2019
Tweet

More Decks by Miłosz Lewandowski

Other Decks in Programming

Transcript

  1. @plnice Android Jetpack: what you need to know in 2019

    Miłosz Lewandowski Senior Android Developer @ Miquido - Play24
  2. @plnice The evolution • Android Jetpack is the next form

    of Support Library • The last version of Support Library is 28.0.0 (released September 21, 2018) • There won’t be Support Library version that is related to API 29! (Android 10) https://youtu.be/Hyt7LR5mXLc
  3. @plnice Jetpack vs AndroidX vs other namespaces • Jetpack ==

    AndroidX • All of Support Library artifacts migrated to the androidx.* namespace… • ...with one exception: Design Support Library com.android.support:design -> com.google.android.material:material • Not a part of Jetpack, hosted and maintained separately https://github.com/material-components/material-components-android
  4. @plnice AndroidX packages versioning • AndroidX packages follow strict semantic

    versioning • major.minor.micro-suffix • alpha, beta, rc releases • Separated from Android API version (contrary to Support Library) ◦ versioning (re)started with 1.0.0 • No more minApi suffixes (e.g. appcompat-v7 -> appcompat)
  5. @plnice The consequences of changes • Major or minor (major.minor.micro)

    version bumps can require some additional changes to your project or include API/behavior changes • Examine release notes before bumping AndroidX packages versions • Remember about transitive dependencies
  6. @plnice The consequences of changes • AndroidX packages are released

    independently • More frequent releases (incl. alpha, beta, rc releases) https://developer.android.com/jetpack/androidx/versions
  7. @plnice Packages, alpha, beta, rc, oh my! • There are

    70 Jetpack packages • Only stable releases are suitable for production… • ...but it’s worth to check what’s coming up (from time to time) • Early feedback matters ◦ Catch bugs before AndroidX package goes out to production ◦ Suggest API and behavior changes • How to track frequent releases of multiple packages?
  8. @plnice How to track frequent releases? • RSS feed ◦

    https://developer.android.com/jetpack/androidx/versions/all-channel
  9. @plnice • Android 10 • Improvements to Activity/Fragment • Composition

    over inheritance/monolith in Activity/Fragment • Benchmarking • Jetpack Compose • Other libraries
  10. @plnice Android 10 and Jetpack • Contextual Notification Actions ◦

    since core 1.2.0-alpha01, currently in rc • Notification Bubbles ◦ since core 1.2.0-alpha01, currently in rc • Dark Mode improvements ◦ recreating Activities and various fixes since appcompat 1.1.0 ◦ various fixes in core 1.2.0-alpha01 ◦ dark theme support in browser 1.2.0-alpha07 • Dark Mode (Material Components): ◦ 1.1.0-beta01 contains Material Dark Theme for all components
  11. @plnice Improvements to Activity/Fragments • layoutId in Activity/Fragment constructor ◦

    since stable fragment 1.1.0 (FragmentActivity, Fragment) ◦ since stable appcompat 1.1.0 (AppCompatActivity) ◦ profit: no need to override onCreateView (in most cases) • FragmentFactory ◦ since stable fragment 1.1.0 ◦ manage the creation of fragment instances, removing the strict requirement to have a no-argument constructor ◦ example: dependency injection
  12. @plnice Improvements to Activity/Fragments • FragmentContainerView ◦ since fragment 1.2.0-alpha02,

    currently in rc ◦ replaces usage of FrameLayout, fixes animation z-index ordering issues and window insets dispatching
  13. @plnice Composition over inheritance/monolith • OnBackPressedDispatcher (available in stable activity

    1.0.0) • SavedStateRegistry (available in stable savedstate 1.0.0) • The shift is to reduce Activity/Fragment’s responsibility • Remove functionalities from Activity/Fragment, provide them via external classes ◦ The pattern is to obtain the object from Activity/Fragment and use its API ◦ The Activity/Fragment is now composed of the several functionalities • Profits: ◦ Activity/Fragment less complex (also Android’s code less complex) ◦ higher flexibility in your code ◦ less method overrides ◦ more control over code structure
  14. @plnice OnBackPressedDispatcher: before (#1) interface OnBackPressedConsumer { fun onBackPressed() }

    class MyFragment : Fragment, OnBackPressedConsumer { override fun onBackPressed() { // Do something } } class MyActivity : FragmentActivity() { override fun onBackPressed() { // Use FragmentManager to find fragment that overrides OnBackPressedConsumer // Dispatch the flow to the Fragment or call super method if not found } }
  15. @plnice OnBackPressedDispatcher: before (#2) typealias BackPressedCallback = () -> Unit

    interface OnBackPressedDispatcher { fun addCallback(callback: BackPressedCallback) } class MyActivity : FragmentActivity(), OnBackPressedDispatcher { private val callbacks = mutableSetOf<BackPressedCallback>() override fun addCallback(callback: () -> Unit) { callbacks.add(callback) } override fun onBackPressed() = when (callbacks.size) { 0 -> super.onBackPressed() else -> callbacks.forEach { it.invoke() } } }
  16. @plnice OnBackPressedDispatcher: before (#2) class MyFragment : Fragment() { override

    fun onAttach(context: Context) { super.onAttach(context) if (context is OnBackPressedDispatcher) { context.addCallback { // Do something } } } } • Remember to unregister the callback!
  17. @plnice OnBackPressedDispatcher: after class MyFragment : Fragment() { override fun

    onAttach(context: Context) { super.onAttach(context) val callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { // Do something } } requireActivity().onBackPressedDispatcher.addCallback(this, callback) } } LifecycleOwner
  18. @plnice SavedStateRegistry: before class MyActivity : AppCompatActivity() { companion object

    { private const val SOME_VALUE_KEY = "some_value" } private lateinit var someValue: String override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString(SOME_VALUE_KEY, someValue) } override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) someValue = savedInstanceState.getString(someValue, "") } }
  19. @plnice SavedStateRegistry: after class MyActivity : AppCompatActivity() { companion object

    { private const val MY_SAVED_STATE_KEY = "my_saved_state" private const val SOME_VALUE_KEY = "some_value" } private lateinit var someValue: String private val savedStateProvider = SavedStateRegistry.SavedStateProvider { Bundle().apply { putString(SOME_VALUE_KEY, someValue) } }
  20. @plnice SavedStateRegistry: after override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) savedStateRegistry

    .registerSavedStateProvider(MY_SAVED_STATE_KEY, savedStateProvider) } fun someMethod() { someValue = savedStateRegistry .consumeRestoredStateForKey(MY_SAVED_STATE_KEY) ?.getString(SOME_VALUE_KEY) ?: "" } }
  21. @plnice Benchmarking • BenchmarkRule ◦ available in stable benchmark 1.0.0

    @get:Rule val benchmarkRule = BenchmarkRule() @UiThreadTest @Test fun simpleScroll() { benchmarkRule.measureRepeated { recyclerView.scrollBy(0, recyclerView.getLastChild().height) } } https://medium.com/androiddevelopers/fighting-regressions-with-benchmarks-in-ci-6ea9a14b5c71
  22. @plnice Jetpack Compose • Next big thing, in developer preview

    • Until October, you needed to download AOSP repository and build a special version of Android Studio • Now androidx.ui packages available on Google’s maven • No release notes yet • Current version: 0.1.0-dev03 implementation("androidx.ui:ui-core:0.1.0-dev03") implementation("androidx.ui:ui-layout:0.1.0-dev03") implementation("androidx.ui:ui-framework:0.1.0-dev03") implementation("androidx.ui:ui-material:0.1.0-dev03") implementation("androidx.ui:ui-foundation:0.1.0-dev03") implementation("androidx.ui:ui-text:0.1.0-dev03")
  23. @plnice What I didn’t mention? • Lifecycle ◦ viewmodel-savedstate (1.0.0,

    currently in rc) ◦ coroutines in Lifecycle and LiveData (2.2.0, currently in rc) • Navigation ◦ scoping ViewModels to a navigation graph - sharing the data between destinations in the same graph (2.1.0 stable) • Room ◦ incremental annotation processor (2.2.0 stable) ◦ @Query methods returning Flow (2.2.0 stable)
  24. @plnice What I didn’t mention? • Biometric ◦ Android 10

    APIs compatible back to Android 6.0 ◦ 1.0.0 stable • ViewPager2 ◦ right-to-left support ◦ vertical orientation ◦ reliable Fragment support ◦ dataset change animations ◦ 1.0.0 stable • ...
  25. @plnice Gradle configuration for AndroidX android.useAndroidX=true The Android plugin uses

    the appropriate AndroidX library instead of a Support Library. android.enableJetifier=true The Android plugin automatically migrates existing third-party libraries to use AndroidX by rewriting their binaries.
  26. @plnice Jetifier • Jetifier goes through all the libraries and

    their transitive dependencies, even if they don’t need to be migrated • Takes 12 seconds on my medium-sized project (see https://proandroiddev.com/the-state-of-jetification-in-early-2019-plus-a-bonus- gradle-plugin-aac5854af910) • Can be a problem when running clean builds (e.g. on CI) • Most of the libraries already migrated to AndroidX: ◦ Firebase, Dagger, Glide, ButterKnife, Epoxy, LeakCanary (2.0) • Some of the libraries didn’t migrate yet: ◦ Facebook SDK • How do I know if can I drop Jetifier?
  27. @plnice Can I drop Jetifier? • https://github.com/plnice/can-i-drop-jetifier • Checks (for

    each of the modules) whether there are any dependencies using support library instead of AndroidX artifacts. ./gradlew -Pandroid.enableJetifier=false canIDropJetifier Cannot drop Jetifier due to following external dependencies: * com.facebook.android:facebook-android-sdk:5.8.0 \-- com.facebook.android:facebook-login:5.8.0 \-- com.android.support:appcompat-v7:27.0.2 or No dependencies on old artifacts! Safe to drop Jetifier.
  28. @plnice Summary • If you didn’t migrate to Jetpack yet,

    now’s the time • Be aware of Jetpack’s new versioning and implications • Check out (from time to time) alpha, beta, rc versions and the release notes • Jetpack is not only a support layer for newer AOSP features… • ...but also provides many useful features... • ...not only bigger, but also smaller ones - still very useful! • Be aware of the Jetifier tool and drop it when you can ◦ If you use my plugin I will be happy :-)