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

Where Did My State Go?

Where Did My State Go?

Subhrajyoti Sen

July 24, 2020
Tweet

More Decks by Subhrajyoti Sen

Other Decks in Technology

Transcript

  1. NO

  2. NO

  3. Dark Theme Introduced in Android 10 Can be changed by

    1. System Toggle 2. AppCompat in-app
  4. Multi-Window Introduced in Android N A slight change in Lifecycle.

    You can’t completely depend on onPause() and onResume()
  5. Multi-Window Introduced in Android N A slight change in Lifecycle.

    You can’t completely depend on onPause() and onResume() screenOrientation will be ignored
  6. Process Death • The device is running low on memory

    and the OS kills your app to free up memory.
  7. Process Death • The device is running low on memory

    and the OS kills your app to free up memory. • It happens if your app is in the Paused/Stopped state.
  8. Process Death • The device is running low on memory

    and the OS kills your app to free up memory. • It happens if your app is in the Paused/Stopped state. • Cannot work around it.
  9. Process Death - Testing 1. Developer Options -> Apps ->

    Background process limit 2. Choose ‘No background processes’ 3. Open your app and put in the background 4. Open another app and switch to your app
  10. Process Death - Testing 1. Put the app in background

    2. adb shell am kill packagename
  11. ViewModel ViewModels persist state across Activity recreation. ViewModels do not

    persist state on process death. Use SavedStateHandle to save state.
  12. ViewModel - SavedStateHandle val viewModel = ViewModelProvider(this, SavedStateVMFactory(this)) .get(MyViewModel::class.java) class

    MyViewModel(val state : SavedStateHandle) : ViewModel() { fun saveProductId(productId: String) { state.set("productId", productId) } fun getProductId(): String { return state.get("productId")?: "" } }
  13. Custom View Views can save their own state. Views need

    to have an ID to be able to save state.
  14. Custom View private class SavedState : BaseSavedState { var value

    = 1 constructor(superState: Parcelable) : super(superState) private constructor(source: Parcel) : super(source) { value = source.readInt() } override fun writeToParcel(out: Parcel, flags: Int) { super.writeToParcel(out, flags) out.writeInt(value) } }
  15. Custom View private class SavedState : BaseSavedState { //.. companion

    object { val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> { override fun createFromParcel(source: Parcel) = SavedState(source) override fun newArray(size: Int) = arrayOfNulls<SavedState?>(size) } } }
  16. Custom View class CustomView(context: Context) : View(context) { var value

    = 1 override fun onSaveInstanceState(): Parcelable { val superState = super.onSaveInstanceState() val state = SavedState(superState) state.value = this.value return state } }
  17. Custom View class CustomView(context: Context) : View(context) { override fun

    onRestoreInstanceState(state: Parcelable) { val savedState = state as SavedState super.onRestoreInstanceState(savedState.superState) this.value = savedState.value } }
  18. Testing Activity/Fragment Recreation Can be done with Espresso Easier with

    AndroidX Test debugImplementation 'androidx.fragment:fragment-testing:$fragment_version'
  19. Testing Fragment Recreation @RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testRecreation()

    { val scenario = launchFragmentInContainer<MyFragment>() // perform actions } }
  20. Testing Fragment Recreation @RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testRecreation()

    { val scenario = launchFragmentInContainer<MyFragment>() // perform actions scenario.recreate() } }
  21. Testing Fragment Recreation @RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testRecreation()

    { val scenario = launchFragmentInContainer<MyFragment>() // perform actions scenario.recreate() // test events } }
  22. Testing Fragment Lifecycle @RunWith(AndroidJUnit4::class) class MyTestSuite { @Test fun testLifecycle()

    { val scenario = launchFragmentInContainer<MyFragment>() scenario.moveToState(State.CREATED) } }