"The specified child already has a parent" error using FragmentStatePagerAdapater

Papajohn000 picture Papajohn000 · Jul 12, 2013 · Viewed 7.2k times · Source

I've tried to implement some of the solutions of all the similar questions but none of them seem to work in my situation. My situation is slightly different because instead of getting the surfaceview from xml I'm creating it through a SurfaceView class and adding it to a FrameLayout. I'm doing this because I want to use a mediaplayer when the surface is created.

Logcat

    07-12 11:02:28.221: E/AndroidRuntime(7055): FATAL EXCEPTION: main
07-12 11:02:28.221: E/AndroidRuntime(7055): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.addViewInner(ViewGroup.java:3337)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.addView(ViewGroup.java:3208)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.addView(ViewGroup.java:3165)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.addView(ViewGroup.java:3145)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.NoSaveStateFrameLayout.wrap(NoSaveStateFrameLayout.java:40)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:915)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.view.ViewPager.populate(ViewPager.java:1064)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.view.ViewPager.populate(ViewPager.java:911)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1432)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.View.measure(View.java:12892)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:594)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:376)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.View.measure(View.java:12892)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.View.measure(View.java:12892)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:812)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:553)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.View.measure(View.java:12892)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4698)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:293)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2268)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.View.measure(View.java:12892)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1159)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2545)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.os.Looper.loop(Looper.java:137)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at android.app.ActivityThread.main(ActivityThread.java:4507)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at java.lang.reflect.Method.invokeNative(Native Method)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at java.lang.reflect.Method.invoke(Method.java:511)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
07-12 11:02:28.221: E/AndroidRuntime(7055):     at dalvik.system.NativeStart.main(Native Method)

My code is as follows:

VideoFragment.java

public class VideoFragment extends Fragment{
private static final String TAG = "Fuck this";
static String vpath;
static Context cxt;
static int pos;
static VideoFragment newInstance(int position, Cursor cursor, Context context) {
    pos = position;

    cursor.moveToPosition(position);
    vpath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
    cxt = context;
    VideoFragment f = new VideoFragment();

    Bundle args = new Bundle();
    args.putInt("position", position);
    f.setArguments(args);

    return f;
}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //mNum = getArguments() != null ? getArguments().getInt("num") : 1;

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View v = inflater.inflate(R.layout.full_image, container, false);

    FrameLayout preview = (FrameLayout) v.findViewById(R.id.framelayout);

    VidView vidview = new VidView(cxt);
    preview.addView(vidview, pos);
    return preview;


}

public class VidView extends SurfaceView implements SurfaceHolder.Callback {
    MediaPlayer player;
    public VidView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        player = new MediaPlayer();

        player.setDisplay(holder);

    try {
        player.setDataSource(vpath);
        player.prepare();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {  
        if (player != null){
            if ( player.isPlaying() )
                player.stop();
        player.reset();
        player.release();
        player = null;
        }

    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)   { 

    }

}

The Activity and the FragmentStatePagerAdapater

public class FullImageActivity extends FragmentActivity  {


private static final String TAG = "MediaPlayer shit";
//MediaPlayer player;
//SurfaceView surfaceview;
SurfaceHolder surfaceHolder;
Gridview gridview = new Gridview();
int width;
int height;
Cursor cursor;
ViewPager viewpager;
PagerAdapter pageradapter;
String path;
int position;
String[] projection = { GridviewData.ROWID, GridviewData.BITMAPPATH, GridviewData.VIDEOFILEPATH};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.image_pager);

    Intent i = getIntent();

    position = i.getExtras().getInt("position");
    path = i.getExtras().getString("videopath");


    cursor = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 
                                gridview.mediaColumns, 
                                MediaStore.Video.Media.DATA + " like ?", 
                                new String[] {Environment.getExternalStorageDirectory().getPath() + "/Reelcam/TheReelcams/%"}, 
                                null); 

    pageradapter = new PagerAdapter(getSupportFragmentManager());
    viewpager = (ViewPager) findViewById(R.id.pager);
    //viewpager.setOffscreenPageLimit(1);
    viewpager.setAdapter(pageradapter);

}


@Override
protected void onPause() {

    super.onPause();
}
@Override
protected void onResume() {
    //surfaceview.setVisibility(View.VISIBLE);
    super.onResume();
}


@Override
protected void onDestroy() {
    cursor.close();
    super.onDestroy();
}

public class PagerAdapter extends FragmentStatePagerAdapter{
    public PagerAdapter(FragmentManager fm) {
        super(fm);
        // TODO Auto-generated constructor stub
    }

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

    @Override
    public Fragment getItem(int position) {
        Log.i(TAG, "in getitem");
        return VideoFragment.newInstance(position, cursor, getApplicationContext());
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return cursor.getCount();
    }

}

Answer

S.D. picture S.D. · Jul 12, 2013

Here:

View v = inflater.inflate(R.layout.full_image, container, false);

FrameLayout preview = (FrameLayout) v.findViewById(R.id.framelayout);

. . . . . . 

return preview;

You are inflating full_image layout to v. But you are returning another view of id frameLayout which may have already a parent (probably v) in the layout. Return v instead.

Make sure you return a View which does not have a parent. Look into R.layout.full_image and see that if R.id.framelayout is already enclosed in a parent ViewGroup.