ViewStub 必须有一个非空的 ViewGroup viewParent

ViewStub must have a non-null ViewGroup viewParent

我正在使用 ViewStubs 在我的布局中加载显示数据。因为我使用 ButterKnife 来绑定布局组件,所以我有自定义的 classes 来保存单个 viewstub 布局的组件,例如一个这样的 viewstub 如下。

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

处理@layout/featured_content组件的class如下:

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);
        }
    }

我这样膨胀布局:

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

在我的片段中的两个不同位置调用了上述方法。它第一次正确充气,但第二次失败,引用 java.lang.IllegalStateException: ViewStub must have a non-null ViewGroup viewParent

我该如何处理这种情况。

Android 像这样膨胀 ViewStub:

  1. 最初以与任何其他视图相同的方式将 ViewStub 添加到视图层次结构
  2. 调用 inflate 时用指定布局替换该视图。

这意味着,当您的代码被第二次调用时,原来的 ViewStub 对象早已从 View 层次结构中分离出来,并且已经被完整的 View 所取代。

就我个人而言,我认为当前形式的 ViewStub 非常不方便,尤其是在使用 ButerKnife 时。幸运的是 class 本身非常简单,您总是可以创建一个自定义的 class,它的作用是一样的,并向其中添加任何需要的方法(例如 isInflatedaddInflateCallback 等.). Android 支持库开发人员也做了同样的事情,顺便说一句。

如果您查看 viewstub.inflate() 函数的源代码,一旦 viewstub 引用的视图被膨胀,它就会从 viewstub 中删除布局引用。

因此,当 viewstub.inflate 第二次被调用时,您总是会收到此错误。预防方法如下:

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