Reputation: 47088
I'm confused about the best practice for saving the states of Views that live inside of fragments in Android.
I thought that setRetainInstance(true)
would do the trick; however, while this does retain the old global View
references declared in the Fragment
, those Views will not be used when inflating the layout. Thus, I have to manually transfer the properties from the old global View references to the new Views in the inflated layout. See the code below for how I'm doing this.
public static class MyFragment extends Fragment {
// I need to save the state of two views in the fragment
ProgressBar mProgress;
TextView mText;
@Override public void onCreate(Bundle savedInstanceState) {
// savedInstanceState == null if setRetainInstance == true
super.onCreate(savedInstanceState);
// Retain the instance between configuration changes
setRetainInstance(true);
}
@Override public View onCreateView(LayoutInflater i, ViewGroup c, Bundle b) {
// Inflate xml layout for fragement (orientation dependent)
View v = i.inflate(R.layout.fragment_main, c, false);
// Grab Views from layout
ProgressBar tmpProgress = (ProgressBar) v.findViewById(R.id.progress);
TextView tmpText = (TextView) v.findViewById(R.id.text);
// If View References exist, transfer state from previous Views
if(mProgress != null){
tmpProgress.setProgress(mProgress.getProgress());
tmpText.setText(mText.getText());
}
// Replace View references
mProgress = tmpProgress;
mText = tmpText;
return v;
}
}
It's my feeling that setRetainInstanceState(true)
should mainly be used for keeping a fragment alive so that background processes can maintain a connection to it. If that's the case should I not be using this method to retain the states of my View
s?
More specifically:
setRetainInstanceState
is true
, is the above code the best way to retain the View
states between orientation calls?setRetainInstanceState(false)
and use Bundle
s to maintain the View states? (Note: bundles cannot be used if setRetainInstance == true
)Upvotes: 2
Views: 5485
Reputation: 2810
Use setRetainInstance
DO NOT keep your view in memory just keep same instance as a kind of Singleton
based on tag
or ID
that you give to your fragment. It's good because when you Fragment
goes to background your view is destroyed and not unecessary memory.
Answering your two questions:
Do not keep your view created! Recreate your view every time onCreateView is called. To keep states and more use global variables.
No, once you set it your Fragment
, Android OS will keep same instance for same tag or ID so when it goes to background keep in mind to save your Bundle
with view state at onSaveInstanceState
to recover view status at next time.
Read more about Fragments lifecycle here: http://developer.android.com/guide/components/fragments.html#Lifecycle
And about onSaveInstanceState
, see more here: http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)
For example you could do something like that:
package com.example.stackoverflowsandbox;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MyFragment extends Fragment {
public static String VIEW_STATE_A = "a";
public static String VIEW_STATE_B = "b";
public static String VIEW_STATE_C = "c";
private String currentState = MyFragment.VIEW_STATE_A;
private View view;
public void changeStateTo( final String newState ) {
if ( this.currentState != newState ) {
this.currentState = newState;
this.updateViewState( this.currentState );
}
}
@Override
public View onCreateView( final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState ) {
this.setRetainInstance( true );
this.view = inflater.inflate( R.layout.my_view, null );
this.updateViewState( this.currentState );
return this.view;
}
@Override
public void onDestroyView() {
this.view = null; // release the reference to GC
super.onDestroyView();
}
private void updateViewState( final String state ) {
// do what you want to do with your view here...
}
}
Change your fragment
state by changeStateTo
.
Upvotes: 5