TMaszko
TMaszko

Reputation: 23

viewPagerAdapter.getItem return fragment which activity is null

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)
    Log.d("ACTIVITY MAIN", "CREATED")
    setupViewPager(bottom_nav)
}

private fun setupViewPager(bottomNavigationView: BottomNavigationView) {
    val viewPagerAdapter = ViewPagerAdapter(supportFragmentManager)
    val trainingFragment = TrainingFragment()
    val magicMileFragment = MagicMileFragment()
    val tournamentFragment = TournamentFragment()
    viewPagerAdapter.add(trainingFragment)
    viewPagerAdapter.add(magicMileFragment)
    viewPagerAdapter.add(tournamentFragment)

    bottomNavigationView.setOnNavigationItemSelectedListener {
        when (it.itemId) {
             R.id.magicMileFragment -> {
                 viewpager.currentItem = 1
                 if(viewPagerAdapter.getItem(1).activity == null)
                    Log.d("NULL ACTIVITY", "NULLL")
             }
             R.id.trainingFragment -> {
                 viewpager.currentItem = 0
             }
            R.id.tournamentFragment -> {
                viewpager.currentItem = 2
            }
        }
        false
    }

I have problem with my fragments inside bottomNavigation.setOnNavigationItemSelectedListener with viewPagerAdapter. After changing an orientation this condition: if(viewPagerAdapter.getItem(1).activity == null) is true. I checked that activity remain null in all fragments inside viewPagerAdapter I didn't attach code with setting an adapter because I don't think it's relevant. Could you explain me why it's happening?

Upvotes: 2

Views: 449

Answers (1)

Aaron
Aaron

Reputation: 3894

That's because getItem (should) always create a new instance of Fragment and does not commit them to transaction. ViewPager gets fragments from instantiateItem or getItem and commits them to transactions, and they will be attached to activity eventually.

So here's the snippet of FragmentPagerAdapter.instantiateItem:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    if (mCurTransaction == null) {
        mCurTransaction = mFragmentManager.beginTransaction();
    }

    final long itemId = getItemId(position);

    // Do we already have this fragment?
    String name = makeFragmentName(container.getId(), itemId);
    Fragment fragment = mFragmentManager.findFragmentByTag(name);
    if (fragment != null) {
        if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
        mCurTransaction.attach(fragment);
    } else {
        fragment = getItem(position);
        if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
        mCurTransaction.add(container.getId(), fragment,
                makeFragmentName(container.getId(), itemId));
    }
    if (fragment != mCurrentPrimaryItem) {
        fragment.setMenuVisibility(false);
        fragment.setUserVisibleHint(false);
    }

    return fragment;
}

ViewPager calls instantiateItem to get fragments, and within the method, it checks if the fragments exist, then return the fragments, otherwise it calls getItem to create new instance of them.

This explains why your activity is null on getItem. But if your getItem does not (always) return new instance of Fragment, then chances are your app will fail because the fragment's activity may not survive a configuration change, say a screen rotation.

Upvotes: 1

Related Questions