Deep Dive Into Android 
State Restoration
TWITTER 
@cyrilmottier 
! 
WEBSITE 
cyrilmottier.com
Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014
Deep dive into android restoration - DroidCon Paris 2014
The story of a newbie 
Android developer
Kevin has just developed his first 
Android app
He discovers an annoying bug: 
Fields are cleared on rotate
3 options
3 options 
Don’t care
3 options 
Don’t care Block orientation
3 options 
Don’t care Block orientation Use configChanges 
Hint: all options are
1 <activity! 
2 android:name=".HomeActivity"! 
3 android:configChanges="orientation">! 
4 ! 
5 <!-- Some sweet IntentFilters. -->! 
6 ! 
7 </activity>
Kevin’s satisfied
Still having issues on…
Still having issues on… 
language changes
1 <activity! 
2 android:name=".HomeActivity"! 
3 android:configChanges="orientation! 
4 ! 
5 <!-- Some annoying IntentFilters. -->! 
6 ! 
7 </activity> 
|locale">
ANGRY! Angry Kevin is
1 <activity! 
2 android:name=".HomeActivity"! 
3 android:configChanges=“orientation|locale|! 
mcc|mnc|touchscreen|keyboard|! 
keyboardHidden|navigation|uiMode|! 
screenLayout|fontScale|screenSize|! 
smallestScreenSize">! 
4 ! 
5 <!-- Some fuc**** IntentFilters. Arrggh! -->! 
6 ! 
7 </activity>
The nightmare continues… 
Still having issues when moving the app to the background
God save the STATE
State restoration 
key components
The container 
Parcel
The container 
Parcel The content 
Primitives types 
Primitives arrays 
Parcelable
The content 
Primitives types 
Primitives arrays 
1 parcel.writeInt(1);! 
2 parcel.writeLong(2L);! 
3 parcel.writeFloat(3F);! 
4 parcel.writeString("Hi!"); 
Parcelable
1 parcel.writeIntArray(new int[]{1, 2, 3});! 
2 parcel.writeLongArray(new long[]{1L, 2L, 3L});! 
3 parcel.writeDoubleArray(new double[]{1, 2, 3});! 
4 parcel.writeStringArray(new String[]{! 
5 "Hi", "Droidcon", "guys!"! 
6 }); 
The content 
Primitives types 
Primitives arrays 
Parcelable
1 public final class Suggestion implements Parcelable {! 
2 ! 
3 public final String id;! 
4 public final String name;! 
5 public final int type;! 
6 ! 
7 public Suggestion(String id, String name, int type) {! 
8 this.id = Objects.requireNonNull(id);! 
9 this.name = Objects.requireNonNull(name);! 
10 this.type = type;! 
11 }! 
12 ! 
13 }
1 @Override! 
2 public int describeContents() {! 
3 return 0;! 
4 }! 
5 ! 
6 @Override! 
7 public void writeToParcel(Parcel dest, int flags) {! 
8 dest.writeString(id);! 
9 dest.writeString(name);! 
10 dest.writeInt(type);! 
11 }! 
12 
13 public static final Parcelable.Creator<Suggestion> CREATOR = ! 
14 new Parcelable.Creator<Suggestion>() {! 
15 public Suggestion createFromParcel(Parcel in) {! 
16 return new Suggestion(in.readString(), // ! 
17 in.readString(), //! 
18 in.readInt());! 
19 }! 
20 ! 
21 public Suggestion[] newArray(int size) {! 
22 return new Suggestion[size];! 
23 }! 
24 };
Parcelable.Creator! 
The base creator interface 
! 
Parcelable.ClassLoaderCreator! 
A creator with the ClassLoader passed on read. 
! 
ParcelableCompat & 
ParcelableCompatCreatorCallbacks! 
Compatibility stuff
Bundle 
A key-value map & type-safe Parcelable
Parcel! 
internally uses reflection 
(required to get the CREATOR instance) 
…i.e. beware Proguard
Activity level 
state restoration
onCreate(null)
onCreate(null)
: non-null Bundle 
onCreate(null) 
onSaveInstanceState( )
onCreate(null) 
onSaveInstanceState( ) 
onCreate( ) 
: non-null Bundle
onCreate(null) 
onSaveInstanceState( ) 
onCreate( ) 
onRestoreInstanceState( ) 
: non-null Bundle
onCreate(null) 
onSaveInstanceState( ) 
onCreate( ) 
onRestoreInstanceState( ) 
: non-null Bundle
onCreate(null) 
onSaveInstanceState( ) 
onCreate( ) 
onRestoreInstanceState( ) 
: non-null Bundle
What to save? 
Non persistent or non reconstructible info
1 public class SearchActivity extends Activity {! 
2 ! 
3 private static final String STATE_OUTWARD = "state:outward";! 
4 ! 
5 private DateComponents mOutward;! 
6 ! 
7 @Override! 
8 protected void onCreate(Bundle inState) {! 
9 super.onCreate(inState);! 
10 ! 
11 if (inState != null) {! 
12 DateComponents components = inState.getParcelable(STATE_OUTWARD);! 
13 if (components != null) {! 
14 setOutward(components);! 
15 }! 
16 }! 
17 }! 
18 ! 
19 @Override! 
20 protected void onSaveInstanceState(Bundle outState) {! 
21 super.onSaveInstanceState(outState);! 
22 outState.putParcelable(STATE_OUTWARD, mOutward);! 
23 }! 
24 }
onSaveInstanceState saves 
Window
onSaveInstanceState saves 
Window Fragments
onSaveInstanceState saves 
Window Fragments Dialogs
Always call the 
SUPER METHODS Android has no guards on save-related methods
android:stateNotNeeded 
For restart-on-crash apps only 
(i.e. launcher app)
Developer options 
Don’t keep activities
Developer options 
Don’t keep activities
View level 
state restoration
Android saves UI state 
AUTOMAGICALLY
Android saves UI state 
AUTOMAGICALLY (aka “It just works!™”)
Android saves UI state 
AUTOMAGICALLY (aka “It just works!™”) 
…except in some cases
Works out-of-the-box if Views 
1. Have an ID 
2. Are “save” enabled 
3. Come from the framework
It always begins with a call to 
saveHierarchyState()
EditText! 
@id/text 
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box
EditText! 
@id/text 
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
SparseArray<Parcelable>
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
SparseArray<Parcelable> 
S1 
EditText! 
@id/text
SparseArray<Parcelable> 
@id/container 
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
S1 
EditText! 
@id/text
EditText! 
@id/text 
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
S2 SparseArray<Parcelable> 
@id/container S1
SparseArray<Parcelable> 
@id/container S1 
@id/text 
S2 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
SparseArray<Parcelable> 
@id/container S1 
@id/text 
S2 
S3 
EditText! 
@id/text
SparseArray<Parcelable> 
@id/container 
@id/text 
@id/check_box 
S1 
S2 
S3 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
Controlling save 
setSaveEnabled(boolean) 
setSaveFromParentEnabled(boolean)
It always ends with a call to 
restoreHierarchyState()
SparseArray<Parcelable> 
@id/container S1 
@id/text S2 
@id/check_box S3 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
SparseArray<Parcelable> 
@id/container S1 
S2 
S3 
@id/text 
@id/check_box 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
SparseArray<Parcelable> 
@id/container S1 
S2 
@id/check_box S3 
S1 
@id/text 
EditText! 
@id/text
SparseArray<Parcelable> 
@id/container S1 
@id/text S2 
@id/check_box S3 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
EditText! 
@id/text 
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
S2 SparseArray<Parcelable> 
@id/container S1 
@id/text 
S2 
@id/check_box S3
SparseArray<Parcelable> 
@id/container S1 
@id/text S2 
@id/check_box S3 
RelativeLayout! 
@id/container 
EditText! 
@id/text 
TextView 
CheckBox! 
@id/check_box
RelativeLayout! 
@id/container 
TextView 
CheckBox! 
@id/check_box 
@id/container S1 
@id/text S2 
@id/check_box S3 
S3 
SparseArray<Parcelable> 
EditText! 
@id/text
Ensure your Views’ IDs are 
unique & constant
1 static class SavedState extends BaseSavedState {! 
2 int checked;! 
3 ! 
4 SavedState(Parcelable superState) { super(superState); }! 
5 ! 
6 private SavedState(Parcel in) {! 
7 super(in);! 
8 checked = in.readInt();! 
9 }! 
10 ! 
11 @Override! 
12 public void writeToParcel(Parcel out, int flags) {! 
13 super.writeToParcel(out, flags);! 
14 out.writeInt(checked);! 
15 }! 
16 ! 
17 public static final Parcelable.Creator<SavedState> CREATOR = ! 
18 new Parcelable.Creator<SavedState>() {! 
19 public SavedState createFromParcel(Parcel in) {! 
20 return new SavedState(in);! 
21 }! 
22 public SavedState[] newArray(int size) {! 
23 return new SavedState[size];! 
24 }! 
25 };! 
26 }
1 @Override! 
2 public Parcelable onSaveInstanceState() {! 
3 final Parcelable superState = super.onSaveInstanceState();! 
4 SavedState ss = new SavedState(superState);! 
5 ss.checked = isChecked() ? 1 : 0;! 
6 return ss;! 
7 }! 
8 ! 
9 @Override! 
10 public void onRestoreInstanceState(Parcelable state) {! 
11 SavedState ss = (SavedState) state;! 
12 super.onRestoreInstanceState(ss.getSuperState());! 
13 setChecked(ss.checked == 1);! 
14 }
FrameLayout! 
@id/root 
ImageBox! 
@id/container1 
CheckBox! 
@id/check_box 
ImageView! 
@id/image 
ImageBox! 
@id/container2 
CheckBox! 
@id/check_box 
ImageView! 
@id/image
FrameLayout! 
@id/root 
ImageBox! 
@id/container1 
ImageView! 
@id/image 
CheckBox! 
@id/check_box 
ImageBox! 
@id/container2 
ImageView! 
@id/image 
CheckBox! 
@id/check_box 
Custom views with children with same IDs
1 static class SavedState extends BaseSavedState {! 
2 ! 
3 SparseArray childrenStates;! 
4 ! 
5 SavedState(Parcelable superState) { super(superState); }! 
6 ! 
7 private SavedState(Parcel in, ClassLoader loader) {! 
8 super(in);! 
9 childrenStates = in.readSparseArray(loader);! 
10 }! 
11 ! 
12 @Override! 
13 public void writeToParcel(Parcel out, int flags) {! 
14 super.writeToParcel(out, flags);! 
15 out.writeSparseArray(childrenStates);! 
16 }! 
17 ! 
18 public static final Creator<SavedState> CREATOR = ParcelableCompat.! 
19 newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {! 
20 @Override! 
21 public SavedState createFromParcel(Parcel source, ClassLoader loader) {! 
22 return new SavedState(source, loader);! 
23 }! 
24 @Override! 
25 public SavedState[] newArray(int size) {! 
26 return new SavedState[size];! 
27 }! 
28 });! 
29 }
1 @Override! 
2 public Parcelable onSaveInstanceState() {! 
3 final Parcelable superState = super.onSaveInstanceState();! 
4 SavedState ss = new SavedState(superState);! 
5 ss.childrenStates = new SparseArray<Parcelable>();! 
6 for (int i = 0; i < getChildCount(); i++) {! 
7 getChildAt(i).saveHierarchyState(ss.childrenStates);! 
8 }! 
9 return ss;! 
10 }! 
11 ! 
12 @Override! 
13 public void onRestoreInstanceState(Parcelable state) {! 
14 SavedState ss = (SavedState) state;! 
15 super.onRestoreInstanceState(ss.getSuperState());! 
16 for (int i = 0; i < getChildCount(); i++) {! 
17 getChildAt(i).restoreHierarchyState(ss.childrenStates);! 
18 }! 
19 }
That has solved nothing! 
Still need to block save/restore dispatch
1 @Override! 
2 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {! 
3 dispatchFreezeSelfOnly(container);! 
4 }! 
5 ! 
6 @Override! 
7 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {! 
8 dispatchThawSelfOnly(container);! 
9 }
Fragment level 
state restoration
Very similar to Activities 
state restoration lifecycle. 
(Fragments are tied to Activity after all)
Fragment blocks Activity 
save mechanism 
with framework 
setSaveFromParentEnabled(false) 
with support library 
NoSaveStateFrameLayout
2 distinct states 
Fragment + View 
common case 
View only 
detach, addToBackStack, etc.
Leveraging save/restore 
Can to be used to create smooth transitions between 
your Activities: 
! 
- Save the state SA of A 
- Start B with no animations passing SA 
- Apply SA to B 
- Transition between A and B was smooth
Summarizing 
in three rules
Always save the state 
An Android app must survive configuration 
changes & low memory conditions.
Only save essential info 
Only save info that is non persistent 
or can not be reconstructed later.
Use correct levels 
Save instance states at the appropriate 
component level: Activity, Fragment or View.
Thank you! 
@cyrilmottier 
cyrilmottier.com
Resources 
Dressed for Iceland • Cécile Bernard 
Moelwynion, Eryri, Cymru • Marc Poppleton 
Happy, Confused, Wink, Sad, Angry • Megan Sheehan 
Floppy-Disk • Alex Auda Samora 
Fonts 
Source Sans Pro 
Courier

More Related Content

PDF
Clean code
PDF
Practical JavaScript Programming - Session 1/8
PDF
Practical JavaScript Programming - Session 4/8
PPTX
Clean Code - A&BP CC
PDF
Practical JavaScript Programming - Session 6/8
PDF
Practical JavaScript Programming - Session 5/8
PPT
Clean code
PPTX
Devoxx 2012 hibernate envers
Clean code
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 4/8
Clean Code - A&BP CC
Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 5/8
Clean code
Devoxx 2012 hibernate envers

What's hot (20)

PPTX
JavaScript Proven Practises
PDF
Seam Glassfish Slidecast
PDF
Vaadin 8 - Data Binding with Binder
PDF
Tame Accidental Complexity with Ruby and MongoMapper
PDF
Csb advertisment
PDF
Alloy Tips & Tricks #TiLon
DOCX
Library management system
PDF
GoCracow #5 Bartlomiej klimczak - GoBDD
PDF
Selectors and normalizing state shape
PDF
Practical JavaScript Programming - Session 8/8
PPTX
How Reactive do we need to be
PDF
Unit testing with zend framework tek11
DOC
Functions
DOCX
VISUALIZAR REGISTROS EN UN JTABLE
PDF
Llibres pel curs 12-13
DOC
Create a Customized GMF DnD Framework
PPTX
How to Bring Common UI Patterns to ADF
KEY
Unit testing with zend framework PHPBenelux
PDF
Let's begin Behavior Driven Development using RSpec
PDF
The Ring programming language version 1.8 book - Part 119 of 202
JavaScript Proven Practises
Seam Glassfish Slidecast
Vaadin 8 - Data Binding with Binder
Tame Accidental Complexity with Ruby and MongoMapper
Csb advertisment
Alloy Tips & Tricks #TiLon
Library management system
GoCracow #5 Bartlomiej klimczak - GoBDD
Selectors and normalizing state shape
Practical JavaScript Programming - Session 8/8
How Reactive do we need to be
Unit testing with zend framework tek11
Functions
VISUALIZAR REGISTROS EN UN JTABLE
Llibres pel curs 12-13
Create a Customized GMF DnD Framework
How to Bring Common UI Patterns to ADF
Unit testing with zend framework PHPBenelux
Let's begin Behavior Driven Development using RSpec
The Ring programming language version 1.8 book - Part 119 of 202
Ad

Viewers also liked (20)

PDF
Chapter 10 - Views Part 2
PDF
Infinum Android Talks #03 - Android Design Best Practices - for Designers and...
PDF
Smart Lock for Password @ Game DevFest Bangkok 2015
PDF
Advanced iOS
ODP
Android App Development - 07 Threading
PPTX
Android async task
PPTX
Android Dialogs Tutorial
PPTX
Android service, aidl - day 1
PPTX
Thread management
PDF
Advance Android Layout Walkthrough
PPT
Lecture Slides for Preferences and Menus [Android ]
PDF
Android service
PDF
Android Threading
PDF
AndroidManifest
PPTX
Android intents, notification and broadcast recievers
PDF
NLP_lectures_English
PPT
Android - Thread, Handler and AsyncTask
PDF
Android intents
PPTX
Efficient Android Threading
PPTX
Android - Intents - Mazenet Solution
Chapter 10 - Views Part 2
Infinum Android Talks #03 - Android Design Best Practices - for Designers and...
Smart Lock for Password @ Game DevFest Bangkok 2015
Advanced iOS
Android App Development - 07 Threading
Android async task
Android Dialogs Tutorial
Android service, aidl - day 1
Thread management
Advance Android Layout Walkthrough
Lecture Slides for Preferences and Menus [Android ]
Android service
Android Threading
AndroidManifest
Android intents, notification and broadcast recievers
NLP_lectures_English
Android - Thread, Handler and AsyncTask
Android intents
Efficient Android Threading
Android - Intents - Mazenet Solution
Ad

Similar to Deep dive into android restoration - DroidCon Paris 2014 (20)

PPT
Hello Android
PDF
Android, the life of your app
PDF
Droidcon2013 android experience lahoda
PDF
Improving android experience for both users and developers
PDF
Don't Make Android Bad... Again
PPTX
Reactive state management with Jetpack Components
PDF
Gabor Varadi - Reactive State Management with Jetpack Components
PPTX
Common mistakes in android development
PPTX
Lesson 3
PPTX
Android
PDF
Introducing Honeycomb
PDF
On a cell phone form factor, ONLY the list fragment shows, or the .pdf
PDF
02 programmation mobile - android - (activity, view, fragment)
PDF
Device fragmentation vs clean code
PDF
Android UI Development: Tips, Tricks, and Techniques
PDF
Android UI Tips, Tricks and Techniques
PDF
Android custom views
PDF
State management in android applications
PDF
Android Design Patterns
PPTX
Android Developer Toolbox 2017
Hello Android
Android, the life of your app
Droidcon2013 android experience lahoda
Improving android experience for both users and developers
Don't Make Android Bad... Again
Reactive state management with Jetpack Components
Gabor Varadi - Reactive State Management with Jetpack Components
Common mistakes in android development
Lesson 3
Android
Introducing Honeycomb
On a cell phone form factor, ONLY the list fragment shows, or the .pdf
02 programmation mobile - android - (activity, view, fragment)
Device fragmentation vs clean code
Android UI Development: Tips, Tricks, and Techniques
Android UI Tips, Tricks and Techniques
Android custom views
State management in android applications
Android Design Patterns
Android Developer Toolbox 2017

More from Paris Android User Group (20)

PDF
Workshop: building your mobile backend with Parse - Droidcon Paris2014
PDF
Workshop: Amazon developer ecosystem - DroidCon Paris2014
PDF
Extending your apps to wearables - DroidCon Paris 2014
PDF
Scaling android development - DroidCon Paris 2014
PDF
Ingredient of awesome app - DroidCon Paris 2014
PDF
Framing the canvas - DroidCon Paris 2014
PDF
Archos Android based connected home solution - DroidCon Paris 2014
PDF
Porting VLC on Android - DroidCon Paris 2014
PDF
Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014
PDF
Buildsystem.mk - DroidCon Paris 2014
PDF
maximize app engagement and monetization - DroidCon Paris 2014
PPTX
Using the android ndk - DroidCon Paris 2014
PPTX
Holo material design transition - DroidCon Paris 2014
PPTX
Death to passwords - DroidCon Paris 2014
PPTX
Google glass droidcon - DroidCon Paris 2014
PPTX
Embedded webserver implementation and usage - DroidCon Paris 2014
PDF
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
PDF
What's new in android 4.4 - Romain Guy & Chet Haase
PDF
Efficient Image Processing - Nicolas Roard
PDF
Build a user experience by Eyal Lezmy
Workshop: building your mobile backend with Parse - Droidcon Paris2014
Workshop: Amazon developer ecosystem - DroidCon Paris2014
Extending your apps to wearables - DroidCon Paris 2014
Scaling android development - DroidCon Paris 2014
Ingredient of awesome app - DroidCon Paris 2014
Framing the canvas - DroidCon Paris 2014
Archos Android based connected home solution - DroidCon Paris 2014
Porting VLC on Android - DroidCon Paris 2014
Robotium vs Espresso: Get ready to rumble ! - DroidCon Paris 2014
Buildsystem.mk - DroidCon Paris 2014
maximize app engagement and monetization - DroidCon Paris 2014
Using the android ndk - DroidCon Paris 2014
Holo material design transition - DroidCon Paris 2014
Death to passwords - DroidCon Paris 2014
Google glass droidcon - DroidCon Paris 2014
Embedded webserver implementation and usage - DroidCon Paris 2014
Petit design Grande humanité par Geoffrey Dorne - DroidCon Paris 2014
What's new in android 4.4 - Romain Guy & Chet Haase
Efficient Image Processing - Nicolas Roard
Build a user experience by Eyal Lezmy

Recently uploaded (20)

PPTX
Benefits of Physical activity for teenagers.pptx
PDF
CloudStack 4.21: First Look Webinar slides
PDF
How IoT Sensor Integration in 2025 is Transforming Industries Worldwide
PDF
The influence of sentiment analysis in enhancing early warning system model f...
PPT
Geologic Time for studying geology for geologist
PDF
sbt 2.0: go big (Scala Days 2025 edition)
PPTX
The various Industrial Revolutions .pptx
PPTX
Build Your First AI Agent with UiPath.pptx
PDF
Convolutional neural network based encoder-decoder for efficient real-time ob...
PDF
Improvisation in detection of pomegranate leaf disease using transfer learni...
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
Architecture types and enterprise applications.pdf
PDF
Consumable AI The What, Why & How for Small Teams.pdf
PDF
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
PPTX
AI IN MARKETING- PRESENTED BY ANWAR KABIR 1st June 2025.pptx
PPTX
2018-HIPAA-Renewal-Training for executives
PPTX
Modernising the Digital Integration Hub
PDF
UiPath Agentic Automation session 1: RPA to Agents
PPTX
Final SEM Unit 1 for mit wpu at pune .pptx
PPT
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...
Benefits of Physical activity for teenagers.pptx
CloudStack 4.21: First Look Webinar slides
How IoT Sensor Integration in 2025 is Transforming Industries Worldwide
The influence of sentiment analysis in enhancing early warning system model f...
Geologic Time for studying geology for geologist
sbt 2.0: go big (Scala Days 2025 edition)
The various Industrial Revolutions .pptx
Build Your First AI Agent with UiPath.pptx
Convolutional neural network based encoder-decoder for efficient real-time ob...
Improvisation in detection of pomegranate leaf disease using transfer learni...
Zenith AI: Advanced Artificial Intelligence
Architecture types and enterprise applications.pdf
Consumable AI The What, Why & How for Small Teams.pdf
Hybrid horned lizard optimization algorithm-aquila optimizer for DC motor
AI IN MARKETING- PRESENTED BY ANWAR KABIR 1st June 2025.pptx
2018-HIPAA-Renewal-Training for executives
Modernising the Digital Integration Hub
UiPath Agentic Automation session 1: RPA to Agents
Final SEM Unit 1 for mit wpu at pune .pptx
Galois Field Theory of Risk: A Perspective, Protocol, and Mathematical Backgr...

Deep dive into android restoration - DroidCon Paris 2014

  • 1. Deep Dive Into Android State Restoration
  • 2. TWITTER @cyrilmottier ! WEBSITE cyrilmottier.com
  • 7. The story of a newbie Android developer
  • 8. Kevin has just developed his first Android app
  • 9. He discovers an annoying bug: Fields are cleared on rotate
  • 12. 3 options Don’t care Block orientation
  • 13. 3 options Don’t care Block orientation Use configChanges Hint: all options are
  • 14. 1 <activity! 2 android:name=".HomeActivity"! 3 android:configChanges="orientation">! 4 ! 5 <!-- Some sweet IntentFilters. -->! 6 ! 7 </activity>
  • 17. Still having issues on… language changes
  • 18. 1 <activity! 2 android:name=".HomeActivity"! 3 android:configChanges="orientation! 4 ! 5 <!-- Some annoying IntentFilters. -->! 6 ! 7 </activity> |locale">
  • 20. 1 <activity! 2 android:name=".HomeActivity"! 3 android:configChanges=“orientation|locale|! mcc|mnc|touchscreen|keyboard|! keyboardHidden|navigation|uiMode|! screenLayout|fontScale|screenSize|! smallestScreenSize">! 4 ! 5 <!-- Some fuc**** IntentFilters. Arrggh! -->! 6 ! 7 </activity>
  • 21. The nightmare continues… Still having issues when moving the app to the background
  • 22. God save the STATE
  • 23. State restoration key components
  • 25. The container Parcel The content Primitives types Primitives arrays Parcelable
  • 26. The content Primitives types Primitives arrays 1 parcel.writeInt(1);! 2 parcel.writeLong(2L);! 3 parcel.writeFloat(3F);! 4 parcel.writeString("Hi!"); Parcelable
  • 27. 1 parcel.writeIntArray(new int[]{1, 2, 3});! 2 parcel.writeLongArray(new long[]{1L, 2L, 3L});! 3 parcel.writeDoubleArray(new double[]{1, 2, 3});! 4 parcel.writeStringArray(new String[]{! 5 "Hi", "Droidcon", "guys!"! 6 }); The content Primitives types Primitives arrays Parcelable
  • 28. 1 public final class Suggestion implements Parcelable {! 2 ! 3 public final String id;! 4 public final String name;! 5 public final int type;! 6 ! 7 public Suggestion(String id, String name, int type) {! 8 this.id = Objects.requireNonNull(id);! 9 this.name = Objects.requireNonNull(name);! 10 this.type = type;! 11 }! 12 ! 13 }
  • 29. 1 @Override! 2 public int describeContents() {! 3 return 0;! 4 }! 5 ! 6 @Override! 7 public void writeToParcel(Parcel dest, int flags) {! 8 dest.writeString(id);! 9 dest.writeString(name);! 10 dest.writeInt(type);! 11 }! 12 13 public static final Parcelable.Creator<Suggestion> CREATOR = ! 14 new Parcelable.Creator<Suggestion>() {! 15 public Suggestion createFromParcel(Parcel in) {! 16 return new Suggestion(in.readString(), // ! 17 in.readString(), //! 18 in.readInt());! 19 }! 20 ! 21 public Suggestion[] newArray(int size) {! 22 return new Suggestion[size];! 23 }! 24 };
  • 30. Parcelable.Creator! The base creator interface ! Parcelable.ClassLoaderCreator! A creator with the ClassLoader passed on read. ! ParcelableCompat & ParcelableCompatCreatorCallbacks! Compatibility stuff
  • 31. Bundle A key-value map & type-safe Parcelable
  • 32. Parcel! internally uses reflection (required to get the CREATOR instance) …i.e. beware Proguard
  • 33. Activity level state restoration
  • 36. : non-null Bundle onCreate(null) onSaveInstanceState( )
  • 37. onCreate(null) onSaveInstanceState( ) onCreate( ) : non-null Bundle
  • 38. onCreate(null) onSaveInstanceState( ) onCreate( ) onRestoreInstanceState( ) : non-null Bundle
  • 39. onCreate(null) onSaveInstanceState( ) onCreate( ) onRestoreInstanceState( ) : non-null Bundle
  • 40. onCreate(null) onSaveInstanceState( ) onCreate( ) onRestoreInstanceState( ) : non-null Bundle
  • 41. What to save? Non persistent or non reconstructible info
  • 42. 1 public class SearchActivity extends Activity {! 2 ! 3 private static final String STATE_OUTWARD = "state:outward";! 4 ! 5 private DateComponents mOutward;! 6 ! 7 @Override! 8 protected void onCreate(Bundle inState) {! 9 super.onCreate(inState);! 10 ! 11 if (inState != null) {! 12 DateComponents components = inState.getParcelable(STATE_OUTWARD);! 13 if (components != null) {! 14 setOutward(components);! 15 }! 16 }! 17 }! 18 ! 19 @Override! 20 protected void onSaveInstanceState(Bundle outState) {! 21 super.onSaveInstanceState(outState);! 22 outState.putParcelable(STATE_OUTWARD, mOutward);! 23 }! 24 }
  • 45. onSaveInstanceState saves Window Fragments Dialogs
  • 46. Always call the SUPER METHODS Android has no guards on save-related methods
  • 47. android:stateNotNeeded For restart-on-crash apps only (i.e. launcher app)
  • 48. Developer options Don’t keep activities
  • 49. Developer options Don’t keep activities
  • 50. View level state restoration
  • 51. Android saves UI state AUTOMAGICALLY
  • 52. Android saves UI state AUTOMAGICALLY (aka “It just works!™”)
  • 53. Android saves UI state AUTOMAGICALLY (aka “It just works!™”) …except in some cases
  • 54. Works out-of-the-box if Views 1. Have an ID 2. Are “save” enabled 3. Come from the framework
  • 55. It always begins with a call to saveHierarchyState()
  • 56. EditText! @id/text RelativeLayout! @id/container TextView CheckBox! @id/check_box
  • 57. EditText! @id/text RelativeLayout! @id/container TextView CheckBox! @id/check_box SparseArray<Parcelable>
  • 58. RelativeLayout! @id/container TextView CheckBox! @id/check_box SparseArray<Parcelable> S1 EditText! @id/text
  • 59. SparseArray<Parcelable> @id/container RelativeLayout! @id/container TextView CheckBox! @id/check_box S1 EditText! @id/text
  • 60. EditText! @id/text RelativeLayout! @id/container TextView CheckBox! @id/check_box S2 SparseArray<Parcelable> @id/container S1
  • 61. SparseArray<Parcelable> @id/container S1 @id/text S2 RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 62. RelativeLayout! @id/container TextView CheckBox! @id/check_box SparseArray<Parcelable> @id/container S1 @id/text S2 S3 EditText! @id/text
  • 63. SparseArray<Parcelable> @id/container @id/text @id/check_box S1 S2 S3 RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 64. Controlling save setSaveEnabled(boolean) setSaveFromParentEnabled(boolean)
  • 65. It always ends with a call to restoreHierarchyState()
  • 66. SparseArray<Parcelable> @id/container S1 @id/text S2 @id/check_box S3 RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 67. SparseArray<Parcelable> @id/container S1 S2 S3 @id/text @id/check_box RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 68. RelativeLayout! @id/container TextView CheckBox! @id/check_box SparseArray<Parcelable> @id/container S1 S2 @id/check_box S3 S1 @id/text EditText! @id/text
  • 69. SparseArray<Parcelable> @id/container S1 @id/text S2 @id/check_box S3 RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 70. EditText! @id/text RelativeLayout! @id/container TextView CheckBox! @id/check_box S2 SparseArray<Parcelable> @id/container S1 @id/text S2 @id/check_box S3
  • 71. SparseArray<Parcelable> @id/container S1 @id/text S2 @id/check_box S3 RelativeLayout! @id/container EditText! @id/text TextView CheckBox! @id/check_box
  • 72. RelativeLayout! @id/container TextView CheckBox! @id/check_box @id/container S1 @id/text S2 @id/check_box S3 S3 SparseArray<Parcelable> EditText! @id/text
  • 73. Ensure your Views’ IDs are unique & constant
  • 74. 1 static class SavedState extends BaseSavedState {! 2 int checked;! 3 ! 4 SavedState(Parcelable superState) { super(superState); }! 5 ! 6 private SavedState(Parcel in) {! 7 super(in);! 8 checked = in.readInt();! 9 }! 10 ! 11 @Override! 12 public void writeToParcel(Parcel out, int flags) {! 13 super.writeToParcel(out, flags);! 14 out.writeInt(checked);! 15 }! 16 ! 17 public static final Parcelable.Creator<SavedState> CREATOR = ! 18 new Parcelable.Creator<SavedState>() {! 19 public SavedState createFromParcel(Parcel in) {! 20 return new SavedState(in);! 21 }! 22 public SavedState[] newArray(int size) {! 23 return new SavedState[size];! 24 }! 25 };! 26 }
  • 75. 1 @Override! 2 public Parcelable onSaveInstanceState() {! 3 final Parcelable superState = super.onSaveInstanceState();! 4 SavedState ss = new SavedState(superState);! 5 ss.checked = isChecked() ? 1 : 0;! 6 return ss;! 7 }! 8 ! 9 @Override! 10 public void onRestoreInstanceState(Parcelable state) {! 11 SavedState ss = (SavedState) state;! 12 super.onRestoreInstanceState(ss.getSuperState());! 13 setChecked(ss.checked == 1);! 14 }
  • 76. FrameLayout! @id/root ImageBox! @id/container1 CheckBox! @id/check_box ImageView! @id/image ImageBox! @id/container2 CheckBox! @id/check_box ImageView! @id/image
  • 77. FrameLayout! @id/root ImageBox! @id/container1 ImageView! @id/image CheckBox! @id/check_box ImageBox! @id/container2 ImageView! @id/image CheckBox! @id/check_box Custom views with children with same IDs
  • 78. 1 static class SavedState extends BaseSavedState {! 2 ! 3 SparseArray childrenStates;! 4 ! 5 SavedState(Parcelable superState) { super(superState); }! 6 ! 7 private SavedState(Parcel in, ClassLoader loader) {! 8 super(in);! 9 childrenStates = in.readSparseArray(loader);! 10 }! 11 ! 12 @Override! 13 public void writeToParcel(Parcel out, int flags) {! 14 super.writeToParcel(out, flags);! 15 out.writeSparseArray(childrenStates);! 16 }! 17 ! 18 public static final Creator<SavedState> CREATOR = ParcelableCompat.! 19 newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {! 20 @Override! 21 public SavedState createFromParcel(Parcel source, ClassLoader loader) {! 22 return new SavedState(source, loader);! 23 }! 24 @Override! 25 public SavedState[] newArray(int size) {! 26 return new SavedState[size];! 27 }! 28 });! 29 }
  • 79. 1 @Override! 2 public Parcelable onSaveInstanceState() {! 3 final Parcelable superState = super.onSaveInstanceState();! 4 SavedState ss = new SavedState(superState);! 5 ss.childrenStates = new SparseArray<Parcelable>();! 6 for (int i = 0; i < getChildCount(); i++) {! 7 getChildAt(i).saveHierarchyState(ss.childrenStates);! 8 }! 9 return ss;! 10 }! 11 ! 12 @Override! 13 public void onRestoreInstanceState(Parcelable state) {! 14 SavedState ss = (SavedState) state;! 15 super.onRestoreInstanceState(ss.getSuperState());! 16 for (int i = 0; i < getChildCount(); i++) {! 17 getChildAt(i).restoreHierarchyState(ss.childrenStates);! 18 }! 19 }
  • 80. That has solved nothing! Still need to block save/restore dispatch
  • 81. 1 @Override! 2 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {! 3 dispatchFreezeSelfOnly(container);! 4 }! 5 ! 6 @Override! 7 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {! 8 dispatchThawSelfOnly(container);! 9 }
  • 82. Fragment level state restoration
  • 83. Very similar to Activities state restoration lifecycle. (Fragments are tied to Activity after all)
  • 84. Fragment blocks Activity save mechanism with framework setSaveFromParentEnabled(false) with support library NoSaveStateFrameLayout
  • 85. 2 distinct states Fragment + View common case View only detach, addToBackStack, etc.
  • 86. Leveraging save/restore Can to be used to create smooth transitions between your Activities: ! - Save the state SA of A - Start B with no animations passing SA - Apply SA to B - Transition between A and B was smooth
  • 88. Always save the state An Android app must survive configuration changes & low memory conditions.
  • 89. Only save essential info Only save info that is non persistent or can not be reconstructed later.
  • 90. Use correct levels Save instance states at the appropriate component level: Activity, Fragment or View.
  • 91. Thank you! @cyrilmottier cyrilmottier.com
  • 92. Resources Dressed for Iceland • Cécile Bernard Moelwynion, Eryri, Cymru • Marc Poppleton Happy, Confused, Wink, Sad, Angry • Megan Sheehan Floppy-Disk • Alex Auda Samora Fonts Source Sans Pro Courier