Alex Kombo
Alex Kombo

Reputation: 3356

ViewStub must have a non-null ViewGroup viewParent

I am using ViewStubs to load show data in my layout. Since I'm using ButterKnife to bind the layout components, I have custom classes that hold the individual viewstub layout's components, e.g one such viewstub is as follows.

 <ViewStub
      android:id="@+id/featuredContentStub"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:inflatedId="@+id/featuredContent"
      android:layout="@layout/featured_content" />

The class to handle the @layout/featured_content components is as follows:

public class FeaturedContentView {
        @BindView(R.id.art)
        ImageView art;
        @BindView(R.id.shade)
        View shade;
        @BindView(R.id.title)
        TextView featuredTitle;
        @BindView(R.id.performer)
        TextView performer;
        @BindView(R.id.featured_title)
        KerningTextView featuredText;
        @BindView(R.id.play_button)
        Button play;
        @BindView(R.id.shareText)
        TextView shareText;
        @BindView(R.id.addToFavorites)
        ImageView addToFavs;

        FeaturedContentView(View view) {
            ButterKnife.bind(this, view);
        }
    }

I inflate the layout like this:

if (viewstub != null) {
        View view = viewstub.inflate();
        featuredContentView = new FeaturedContentView(view);
}

The above method is called in two different places in my fragment. It inflates correctly the first time but fails the second time citing java.lang.IllegalStateException: ViewStub must have a non-null ViewGroup viewParent.

How can i handle this situation.

Upvotes: 7

Views: 11288

Answers (2)

Deep Lathia
Deep Lathia

Reputation: 770

If you look at source code of the viewstub.inflate() function, once the view referenced by the viewstub is inflated it removes the layout reference from the viewstub.

Hence you'll always get this error when viewstub.inflate gets called the second time. Here's how to prevent it:

if (mViewStub.getParent() != null) {
   mViewStub.inflate();
} else {
   mViewStub.setVisibility(View.VISIBLE);
}

Upvotes: 3

user1643723
user1643723

Reputation: 4222

Android inflates ViewStub like this:

  1. Initially add a ViewStub to View hierarchy same way as any other View
  2. Replace that View with specified layout when you call inflate.

This means, that when your code is called second time, the original ViewStub object is long detached from View hierarchy and already replaced by the full View.

Personally, I think that ViewStub in it's current form is highly inconvenient, especially when working with ButerKnife. Fortunately the class itself is very simple, you can always create a custom class, which does the same and add any required methods to it (such as isInflated, addInflateCallback etc.). Android support library developers have dones the same, btw.

Upvotes: 8

Related Questions