应用程序在向viewpager添加新数据时崩溃



我创建了一个ViewPager,我使用bitmapArray在ViewPager中显示图像。一切工作正常,但当我添加一个新的数据和调用notifydatasetchange,应用程序崩溃。

在这个应用程序中,我正在下载歌曲,并从该文件中获取从下载的歌曲的位图,并在位图数组中添加。

给出如下exception:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

我无法找到导致此异常的原因

ViewPager的适配器类是:

public class CoverFlowPagerAdapter extends PagerAdapter {
    ArrayList<Bitmap> mBitmapArray;
    Context c;
    interface CoverFlowClick {
        public void coverClick(int coverFlowPosition);
    }
    CoverFlowClick mCoverFlowClick;
    public CoverFlowPagerAdapter(Context c, ArrayList<Bitmap> mBitmapArray) {
        this.c = c;
        this.mBitmapArray = mBitmapArray;
        mCoverFlowClick = (CoverFlowClick) c;
    }
    @Override
    public int getCount() {
        return mBitmapArray.size();
    }
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (object == view);
    }
    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        ImageView imageView;
        View v = null;
        LayoutInflater inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v=inflater.inflate(R.layout.coverflow_item,null);
        imageView= (ImageView) v.findViewById(R.id.coverFlowImage);
        imageView.setImageBitmap(mBitmapArray.get(position));
        container.addView(imageView);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(c, "Clicked::--" + position, Toast.LENGTH_SHORT).show();
                mCoverFlowClick.coverClick(position);
            }
        });
        return imageView;
    }
    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((ImageView) object);
    }
}

我将位图添加到数组中,并像这样调用notifydatasetchanged:

@Override
    public void updateSongList(String songName) {
        getBitmapArray(songName);
        mCoverFlowAdapter.notifyDataSetChanged();
    }

编辑:我的自定义布局文件是

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ImageView
        android:id="@+id/coverFlowImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

我的getBitmapArray函数是

public void getBitmapArray(String songName) {
        Bitmap bitmap = null;
        path = Environment.getExternalStorageDirectory() + "/AppDownloads/" + songName;
        File file = new File(path);
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file.getAbsolutePath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            metaRetriver.setDataSource(inputStream.getFD());
        } catch (IOException e) {
            e.printStackTrace();
        }
        art = metaRetriver.getEmbeddedPicture();
        if (art != null) {
            bitmap = BitmapFactory
                    .decodeByteArray(art, 0, art.length);
        }
        if (bitmap != null) {
            mBitmapArray.add(bitmap);
        } else {
            Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.unknown_album);
            mBitmapArray.add(icon);
        }
    }

不要让LinearLayout作为ImageView的父元素,而是让ImageView作为Layout的ROOT元素,如下所示:-

<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/coverFlowImage"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

在适配器中:-

@Override
public Object instantiateItem(ViewGroup container, final int position) {
    LayoutInflater inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    ImageView imageView = (ImageView) inflater.inflate(R.layout.coverflow_item, container, false);
    imageView.setImageBitmap(mBitmapArray.get(position));
    container.addView(imageView);
    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(c, "Clicked::--" + position, Toast.LENGTH_SHORT).show();
            mCoverFlowClick.coverClick(position);
        }
    });
    return imageView;
}

如果你想使用一个LinearLayout作为ROOT然后而不是添加ImageView到容器,添加膨胀视图,并返回它在instantiateItem方法。

同时将destroyItem方法改为

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView(object);
}

在您的自定义布局文件coverflow_item.xml中已经包含了ImageView

再次尝试使用

在相同的容器中添加

container.addView (imageView);

这就是它抛出异常的原因。

要克服它,您需要更改

container.addView(imageView);

container.addView(v);

和这个

return imageView;

return v;
编辑:

也修改一下

container.removeView((ImageView) object); 

container.removeView((LinearLayout)object)

看这里:

   imageView.setImageBitmap(mBitmapArray.get(position));
    container.addView(imageView);

每次你添加biotmap时,它都是添加到同一个容器中,现在一个容器怎么能在它上面添加另一个视图呢?所以你需要删除旧视图:像这样

  @Override
public void updateSongList(String songName) {
    getBitmapArray(songName);
    container.removeView((ImageView) object)
    mCoverFlowAdapter.notifyDataSetChanged();
}

PS:说明代码,请确保你传递正确的参数如果有帮助请告诉我:)

我最近实现了这个,这是我的instantiateItem方法(使其可读性最小)

 @Override
  public Object instantiateItem(View collection, int position) {
     Evaluation evaluation = evaluations.get(position); 
     View layout = inflater.inflate(R.layout.layout_evaluation, null);
     TextView evaluationSummary = (TextView) layout.findViewById(R.id.evaluation_summary);
     evaluationSummary.setText(evaluation.getEvaluationSummary());
     ((ViewPager) collection).addView(layout);
   return layout;
}
 @Override
 public void destroyItem(View collection, int position, Object view) {
    ((ViewPager) collection).removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
   return view == object;
}

因此,对于显示的页面,我使用位置作为索引从评估列表中获取数据。然后膨胀有视图的布局,我也会添加我的数据。然后我得到TextView来设置评估摘要文本。然后整个布局被添加到ViewPager中。最后,Layout也被返回。

如果有帮助请告诉我