[wish] Automatically save and restore View state

warwound

Expert
Licensed User
Longtime User
Why does B4A not automatically save and restore View state as native Android does?

I needed to create an Activity that contained lots (24) of EditText Views, and the Activity needed to save and restore all user entered data on orientation change.

I started to create the Activity using B4A then thought it'd be interesting to try and create the entire Activity using java and add it to my B4A project.
(Just as PreferenceActivity is a java Activity that you add to a B4A project).

I started with a template Activity in Eclipse:

B4X:
public class ResumeEditor extends Activity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(BA.applicationContext.getResources().getIdentifier("submit_resume", "layout", BA.packageName));
   }

   @Override
   protected void onPause() {
      super.onPause();
   }

   @Override
   protected void onResume() {
      super.onResume();
   }

}

submit_resume.xml is a layout file that contains a ScrollView and 24 EditText Views.

I added the Activity to my manifest and ran my B4A project.
It worked as expected and i entered some text into various EditTexts and rotated my device - the Activity was re-created with my entered data automatically saved and restored.
That surprised me as i thought i'd have to create more code to save and restore that user entered data.

So i did some research wondering why B4A doesn't have this functionality, there's an interesting article here: Views saving instance state in Android | Charles Harley:

How saving instance state works

The instance state of each view within an activity is saved in shared persisted data with the state for each view referenced using the view’s ID. Hence why the IDs need to be unique.

To save state the activity traverses the layout hierarchy and for each view it encounters it calls View.saveHierarchyState() which in turn calls View.dispatchSaveInstanceState(). If the view has an ID this method calls View.onSaveInstanceState(), which saves its state to a Parcelable object and returns it. View.dispatchSaveInstanceState() then takes the Parcelable and saves it to the shared persisted data using the ID of the view.

Restoring state is a very similar process with the activity traversing the layout hierarchy and for each view it calls View.restoreHierarchyState() which in turn calls View.dispatchRestoreInstanceState(). If the view has an ID this method retrieves the corresponding Parcelable from the shared persisted data and passes it through to View.onRestoreInstanceState(), which then restores the view’s state.

So all my EditText Views have unique ids defined in the layout file and their state is automatically saved and restored - very useful!

But why doesn't a B4A Activity behave the same?
I see the ViewWrapper class assigns each B4A View a unique integer id so that not the reason.

Does Android only restore View state after onCreate() has executed, so any Views added to an Activity after that method has executed do not have their state restored...?

I updated my Activity moving the code to load my layout from onCreate() to onResume():

B4X:
public class ResumeEditor extends Activity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
   }

   @Override
   protected void onPause() {
      super.onPause();
   }

   @Override
   protected void onResume() {
      super.onResume();
      setContentView(BA.applicationContext.getResources().getIdentifier("submit_resume", "layout", BA.packageName));
   }

}

EditText data was no longer automatically restored.
Looking at the java source for a compiled B4A Activity i see that no Views are actually added to the Activity in onCreate(), they are loaded later in the code after the Activity has Layout dimensions.
So that explains why B4A doesn't automatically restore View state - presumable View state is saved though, it is just not restored?

Thinking in theory now...

Could a reference to the savedInstanceState Bundle (passed to onCreate) be created in onCreate and later on in the code once Views have been added the ids of all Views with a saved state be looked for and if found have their state restored?

Seems a shame that we (B4A users) don't get this (extremely) useful functionality.

Martin.
 
Top