1

I'm trying to implement a gallery.

Since gallery widget has been deprecated... to implement it and have paging scroll effect, I'm using fragment(android compatibility v4) to do this.

Everything looks fine, until scroll back...my APP just force closed due to :

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

Looks like it re-get an ImageView when scroll back to display previous photo.

And I have no idea how to fix this problem...

Here's my xml & code

[XML]

<android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_below="@id/head" android:layout_width="wrap_content" android:layout_height="350dp" android:layout_marginTop="35dp" />

[Code]

public class PhotoView extends FragmentActivity
{
  private Button btnBack=null;
  private ClickHandler click=null;
  private ViewPager pager=null;
  private ArrayList<ImageView> imgList=new ArrayList<ImageView>();

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.photo_show);
    initUI();
    handler.sendEmptyMessage(0);
  }

  private void initUI()
  {
    btnBack=(Button)findViewById(R.id.btnBack);
    btnBack.setOnClickListener(click);
    pager=(ViewPager)findViewById(R.id.pager);
  }

  private Handler handler=new Handler()
  {
    public void handleMessage(Message msg)
    {
      loadPhotos();
    }
  };

  private void loadPhotos()
  {
    for(int i=0; i<Constants.PHOTO_LIST.size(); i++)
    {
      ImageView img=new ImageView(this);
      img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
      imgList.add(img);
      new ImageDL(Constants.PHOTO_LIST.get(i).getFileId(), Params.IMAGE_SIZE_PARAM_ORIGINAL).execute(img); // async D/L photo
    }
    pager.setAdapter(new PhotoAdapter(getSupportFragmentManager()));
  }

  @Override
  public void onBackPressed()
  {
    super.onBackPressed();
    btnBack.performClick();
    return;
  }

  @Override
  protected void onStop()
  {
    super.onStop();
    for(int i=0; i<imgList.size(); i++) //Do recycle when activity stopped, but I'm not yet sure this code is right...
    {
      Drawable drawable=imgList.get(i).getDrawable();
      if(drawable instanceof BitmapDrawable)
      {
        BitmapDrawable bitmapDrawable=(BitmapDrawable) drawable;
        Bitmap bitmap=bitmapDrawable.getBitmap();
        bitmap.recycle();
      }
    }
    imgList.clear();
    imgList=null;
  }

  private class ClickHandler implements OnClickListener
  {
    public void onClick(View v)
    {
      if(v==btnBack)
      {
        finish();
        overridePendingTransition(R.anim.lr1, R.anim.lr2);
        System.gc();
      }
    }
  }

  private class PhotoAdapter extends FragmentPagerAdapter
  {
    public PhotoAdapter(FragmentManager mgr)
    {super(mgr);}

    @Override
    public int getCount()
    {
      return(imgList.size());
    }

    @Override
    public Fragment getItem(int position)
    {
      return(new PhotoFragment(position));
    }
  }

  private class PhotoFragment extends Fragment 
  {
    private int index=-1;

    private PhotoFragment(int index)
    {this.index=index;}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
      return imgList.get(index);
    }
  }
}

That's first time I used Fragment API in my code, I'm not sure the code logic I done is right...

Is there any idea to help me to fix this problem, or another better way to implement gallery(with paging scroll) in Android 2.3 ~ 4.x ?

RRTW
  • 3,160
  • 1
  • 35
  • 54

1 Answers1

0

You should not use imgList as a cache.

The problem with your implementation of onCreateView() is that : . At page 0, ViewPager will add the imageView into page 0, and add imageView into its layout (parent view) ( I think). . When you scroll back to page 0, ViewPager will call onCreateView() again, thus getting error as it try to re-add the already-added imageView into its layout:

java.lang.IllegalStateException: The specified child already has a parent.

So you should not use imgList inside loadPhotos() method; and instead initialize imageView inside onCreateView() instead.

Modified code:

 private void loadPhotos()
  {

    pager.setAdapter(new PhotoAdapter(getSupportFragmentManager()));
  }


public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
      ImageView img=new ImageView(this);
      img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

      new ImageDL(Constants.PHOTO_LIST.get(i).getFileId(),  Params.IMAGE_SIZE_PARAM_ORIGINAL).execute(img); // async D/L photo


      return img;
}
duchuy
  • 604
  • 5
  • 9