Reputation: 7037
Consider the following overly simplified example. I have a LinearLayout
with a list of items (EditTexts
). The number of items is not known at compile time (for example it might be a game menu screen where the user has just selected the number of players and on this screen they are entering each individual player's name).
The obvious way to do this is to have a container layout defined in xml (R.layout.list
), and individual item layouts defined in xml (R.layout.item
); which would look something like this:
public class Main extends Activity {
private static final String FRAG_TAG = "ITEMS_FRAGMENT";
private static final int NUM_ITEMS = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = (LinearLayout) getLayoutInflater().inflate(R.layout.list, null, false);
for (int i = 0; i<NUM_ITEMS; i++) {
ll.addView(getLayoutInflater().inflate(R.layout.item, null, false));
}
setContentView(ll);
}
}
With the R.layout.list
and R.layout.item
layouts respectively:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list" />
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/item"
android:singleLine="true"/>
The problem is that on an orientation change, the fact that all items have the same ID (R.id.item
) confuses the restoration process. The end result is that the state of the last item is restored to all items in the list (i.e. if the last item's EditText
has "hi" in it, every EditText
will have "hi" in it after the orientation chance).
In the instance of this in my code, each item has a CheckBox
that I can get the state of with a isCheckboxChecked(LinearLayout list, int itemNumber)
function that relies on the fact that each item has a view with ID R.id.checkbox
. Is there a proper way to do view state restoration that accepts there may be multiple items inflated from the same XML resource (and consequently will have the same ID)?
(ListView
is not appropriate for this case, but it handles this correctly. How does it restore state correctly when all of it's items typically have the same ID?)
Upvotes: 2
Views: 944
Reputation: 20406
Android stores states by associating them with element's ID. If all elements have same ID, then a state associated with this ID will be restored to all elements with this ID. LisView
does it very differently. It always reads values from Adapter by element position. Because views with the same ID will have different position in the list, they will have different values too.
If your case you have couple of options.
1) You need to assign different ID'S to your items before adding them to the LinearLayout
by calling setId()
method. You need to define those ID's in Android resources firs (e.g. <item type="id" name="item_01" />
etc.).
2) You need to override onSaveInstanceState(Bundle outState)
, go through the children of LinearLayout and store their texts into outState
bundle associating text with children's index. Then in onRestoreInstanceState()
you need to read states from savedInstanceState
and set them to your views correspondingly.
3) You use ListView
and when user enters text, your adapter persists data (e.g. into a file or database). When configuration changes, or on the next start of Activity
your adapter will read those stored values, and they will be restored properly.
Hope one of the options can help you.
Upvotes: 4