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

Frustration-free orientation changes

cketti
April 24, 2018

Frustration-free orientation changes

Many apps do unexpected things when a user rotates the device. A message that has been painfully composed using the on-screen keyboard is just gone. Dialogs are disappearing. Data that took a while to load and display is gone and now the app is making the user wait again.

All of this is very frustrating to users. But if you know that an Activity is destroyed and then recreated on orientation change, this is not too surprising to you. Still, many beginners don’t know what is going on behind the scenes and consequently come up with flawed or incomplete ways to deal with the lifetime of an Activity.

If you have ever “fixed” a bug by changing your app’s manifest to manually handle orientation changes or by locking the device orientation, this talk is for you. It aims to give attendees a better understanding of the Activity lifetime/lifecycle. And we will look at the fundamental ways to deal with this situation. So you can write better apps.

cketti

April 24, 2018
Tweet

More Decks by cketti

Other Decks in Technology

Transcript

  1. Handle the orientation change yourself SearchActivity.kt: override fun onConfigurationChanged(newConfig: Configuration)

    { super.onConfigurationChanged(newConfig) if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { portraitOnlyView.setVisibility(View.GONE) } else { portraitOnlyView.setVisibility(View.VISIBLE) } }
  2. Types of configuration changes • locale • density • fontScale

    • keyboard • keyboardHidden • layoutDirection • mcc • mnc • navigation • screenLayout • smallestScreenSize • touchscreen • uiMode • orientation • screenSize
  3. Retain an object during a configuration change • Activity.onRetainNonConfigurationInstance() +

    getLastNonConfigurationInstance() • FragmentActivity.onRetainCustomNonConfigurationInstance() + getLastCustomNonConfigurationInstance() • Loaders • Fragment.setRetainInstance(true) • Android Architecture Components: ViewModel
  4. No.

  5. Limitations “A Bundle object isn't appropriate for preserving more than

    a trivial amount of data because it consumes system-process memory” – The Activity Lifecycle | Android Developers
  6. What state is saved for you? • Activity stack •

    Fragment stack • Platform UI widgets save user-modifiable UI state ◦ Views need to have an ID set
  7. What state should you save? • As little as possible,

    as much as necessary • User input • Reference to original data source ◦ Database ID ◦ URL ◦ File name
  8. Timing java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at

    android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053) at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079) at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678) at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632) …
  9. Object references Don’t hold on to any object that references

    your Activity instance • Views • Inner classes in Activity
  10. Being restored while waiting for user input EditUserActivity ImagePickerActivity Load

    User object startActivityForResult() onActivityResult() Update User object
  11. Being restored while waiting for user input EditUserActivity ImagePickerActivity startActivityForResult()

    onActivityResult() Load User object Update User object Load User object
  12. Manual testing • Rotate the device • Change language •

    Change font size • Change display size
  13. Manual testing • Rotate the device • Change language •

    Change font size • Change display size • Developer options ◦ Don’t keep activities
  14. Manual testing • Rotate the device • Change language •

    Change font size • Change display size • Developer options ◦ Don’t keep activities ◦ Background process limit
  15. Summary • Always save state • Retain an object as

    optimization • Don’t update the UI when you’re not supposed to • Check out ViewModel + LiveData