Tom Fobear
Tom Fobear

Reputation: 6749

ViewStub reinflates last view inflated on first pass of onCreate

I have a bug with my activity.

I have three view stubs in my linear layout like so -

<ViewStub 
 android:id="@+id/index_1"
 android:layout="@layout/index_edittext" 
 android:layout_width="fill_parent"
 android:layout_height="wrap_content" />
<ViewStub 
 android:id="@+id/index_2"
 android:layout="@layout/index_edittext" 
 android:layout_width="fill_parent"
 android:layout_height="wrap_content" />
<ViewStub 
 android:id="@+id/index_3"
 android:layout="@layout/index_edittext" 
 android:layout_width="fill_parent"
 android:layout_height="wrap_content" />

my onCreate conditionally checks what to inflate:

for (int i = 0; i < 3; i++) {
    int id = convertIndexToId(i); //will turn i into R.id.index_1
    ViewStub stub = findViewById(id);
    if (bShouldBeSpinner) {
        stub.setLayoutResource(R.layout.index_spinner);
        View root = stub.inflate();
        Spinner spin = (Spinner)root.findViewById(R.id.my_spinner);
        spinner.setAdapter(adapter);
        spinner.setSelection(0);
    }
    else {
        stub.setLayoutResource(R.layout.index_edittext);
        View root = stub.inflate();
        EditText et = (EditText)root.findViewById(R.id.my_edittext);
        //et.phoneHome(); just kidding
        et.setText(String.valueOf(System.currentTimeMillis()));
    }
}

I force bShouldBeSpinner to false. The output of the edittext's is as follows:
1300373517172
1300373517192
1300373517221

However, when I rotate the screen and onCreate is called a second time the output is this:
1300373517221
1300373517221
1300373517221

Initially that made me think you should only inflate the view once, and the heirarchy is kept inbetween onCreate's... however when i only run it the first time the second time no views are shown for the stubs.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <Spinner style="@style/SearchInput" android:id="@+id/my_spinner" />
</LinearLayout>

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <EditText style="@style/SearchInput" android:id="@+id/my_edittext" />
</LinearLayout>

I feel the documentation is assuming something that I did not notice or am missing. Does anyone see what I am doing wrong?

EDIT

I added to the view stubs android:inflatedId="index_1_root"... etc

it is the strangest thing, when I add these lines after the for loop:

EditText v = indexRoot1.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v);

EditText v2 = indexRoot2.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v2);

the output says (I believe) they are references to different EditTexts.

EditTExt: android.widget.EditText@47210fe8
EditTExt: android.widget.EditText@47212ba8

So they are getting inflated again, but the text is set to what the last edittext was set to on the first pass.

Upvotes: 1

Views: 2571

Answers (2)

Tom Fobear
Tom Fobear

Reputation: 6749

Instead of using ViewStubs, I added an id to the root of those stubs (android:id="index_roots") and used

view.addView( (isSpinner) ? 
    new Spinner(this) : new EditText(this) ); 

to fix this problem, I will however not accept this answer right away, I'll allow others to answer using the method I was going for.

Upvotes: 1

pawelzieba
pawelzieba

Reputation: 16082

There may be some issues when recreating views of different types with the same id. ViewStub is replaced by inflated view.
I suggest using

setInflatedId(int inflatedId)

to distinguish inflated views.
Hope that help.

Upvotes: 1

Related Questions