Guilherme Lima Pereira
Guilherme Lima Pereira

Reputation: 1434

Fragment already added with FragmentPagerAdapter

I have an Activity with ViewPager and this ViewPager holds 3 fragments.

I'm using FragmentPagerAdapter to create the Fragments, like this:

    class ViewPagerUser(fragmentManager: FragmentManager, private val matchDetails: MatchDetails, private val context: Context) : FragmentPagerAdapter(fragmentManager) {

    // Returns total number of pages
    override fun getCount(): Int {
        return NUM_ITEMS
    }

    // Returns the fragment to display for that page
    override fun getItem(position: Int): Fragment? {
        when (position) {
            0 -> return FragmentDetailMatchInfoUser.newInstance(matchDetails)
            1 -> return FragmentDetailMatchParticipantsUser.newInstance(matchDetails)
            2 -> return FragmentDetailMatchWall.newInstance(matchDetails)
            else -> return null
        }
    }

    // Returns the page title for the top indicator
    override fun getPageTitle(position: Int): CharSequence? {
        when (position) {
            0 -> return context.getString(R.string.info)
            1 -> return context.getString(R.string.player)
            2 -> return context.getString(R.string.wall)
            else -> return null
        }
    }

    companion object {
        private val NUM_ITEMS = 3
    }
}

This is how I use it

    if (matchDetails != null && (matchDetails.cancelled!! || screenType == App.USER || matchDetails.matchStatus == 40 || matchDetails.matchStatus == 50)) {
        adapterViewPager = ViewPagerUser(supportFragmentManager, matchDetails, this)
    } else if (screenType == App.ORGANIZER) {
        adapterViewPager = ViewPagerOrganizer(supportFragmentManager, matchDetails!!, this)
    }

    viewPager?.adapter = adapterViewPager

    viewPager?.offscreenPageLimit = 3

I thought this was the best way to handle Fragments inside the ViewPager, but I'm getting many reports on Crashlytics of "Fragment already added" as you can see in the log bellow:

Fatal Exception: java.lang.IllegalStateException: Fragment already added: FragmentDetailMatchInfoUser{b17d64 #0 id=0x7f090551 android:switcher:2131297617:0}
   at android.support.v4.app.FragmentManagerImpl.addFragment(Unknown Source)
   at android.support.v4.app.BackStackRecord.addOp(Unknown Source)
   at android.support.v4.app.FragmentManagerImpl.executeOps(Unknown Source)
   at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(Unknown Source)
   at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(Unknown Source)
   at android.support.v4.app.FragmentManagerImpl.execSingleAction(Unknown Source)
   at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(Unknown Source)
   at android.support.v4.app.FragmentPagerAdapter.finishUpdate(Unknown Source)
   at android.support.v4.view.ViewPager.initViewPager(Unknown Source)
   at android.support.v4.view.ViewPager.populate(Unknown Source)
   at android.support.v4.view.ViewPager.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.support.design.widget.CoordinatorLayout.onMeasureChild(Unknown Source)
   at android.support.design.widget.HeaderScrollingViewBehavior.onMeasureChild(Unknown Source)
   at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onMeasureChild(Unknown Source)
   at android.support.design.widget.CoordinatorLayout.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:19883)
   at android.support.constraint.ConstraintLayout.internalMeasureChildren(Unknown Source)
   at android.support.constraint.ConstraintLayout.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
   at android.support.v7.widget.ContentFrameLayout.onMeasure(Unknown Source)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
   at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
   at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6087)
   at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
   at com.android.internal.policy.DecorView.onMeasure(DecorView.java:689)
   at android.view.View.measure(View.java:19883)
   at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2293)
   at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1384)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1637)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1272)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6408)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
   at android.view.Choreographer.doCallbacks(Choreographer.java:686)
   at android.view.Choreographer.doFrame(Choreographer.java:621)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
   at android.os.Handler.handleCallback(Handler.java:751)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6165)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)

I went through almost every question related to this problem here in Stackoverflow and the suggested answers couldn't help me... The bug always comes back.

Is there anything I'm doing wrong?

Upvotes: 1

Views: 7768

Answers (3)

tuanpv
tuanpv

Reputation: 11

I had the same problem and I was resolved by adding a 2nd parameter to the FragmentPagerAdapter like this:

class ViewPagerUser(fragmentManager: FragmentManager, private val matchDetails: MatchDetails, private val context: Context) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {...}

More: FragmentPagerAdapter(fragmentManager) is deprecated, you must be change to FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) and the problem will be solved.

Upvotes: 0

Bishoy Kamel
Bishoy Kamel

Reputation: 2355

Use isAdded() to check whether or not the fragment is detached from the activity.

if (!mFragmentDetailMatchInfoUser.isAdded()) {
    return FragmentDetailMatchInfoUser.newInstance(matchDetails);
}

and also for the two fragments.

Upvotes: 0

snitsaruk
snitsaruk

Reputation: 472

This reports may be caused because you are creating new instance of a fragment every time ViewPager asks for a fragment.

You should try creating fragment instances when you create your ViewPager:

class ViewPagerUser(fragmentManager: FragmentManager, private val matchDetails: MatchDetails, private val context: Context) : FragmentPagerAdapter(fragmentManager) {

private val fragmentDetailMatchInfoUser = FragmentDetailMatchInfoUser.newInstance(matchDetails)
private val fragmentDetailMatchParticipantsUser = FragmentDetailMatchParticipantsUser.newInstance(matchDetails)
private val fragmentDetailMatchWall = FragmentDetailMatchWall.newInstance(matchDetails)

    // Returns total number of page
    override fun getCount(): Int {
        return NUM_ITEMS
    }

    // Returns the fragment to display for that page
    override fun getItem(position: Int): Fragment? {
        when (position) {
            0 -> return fragmentDetailMatchInfoUser
            1 -> return fragmentDetailMatchParticipantsUser
            2 -> return fragmentDetailMatchWall
            else -> return null
        }
    }

    // Returns the page title for the top indicator
    override fun getPageTitle(position: Int): CharSequence? {
        when (position) {
            0 -> return context.getString(R.string.info)
            1 -> return context.getString(R.string.player)
            2 -> return context.getString(R.string.wall)
            else -> return null
        }
    }

    companion object {
        private val NUM_ITEMS = 3
    }
 }

I had similar problem and it helped me. Hope it will help you too.

Upvotes: 1

Related Questions