How can I switch between two fragments, without recreating the fragments each time?

后端 未结 10 1768
孤独总比滥情好
孤独总比滥情好 2020-12-08 00:19

I\'m working on an android application, that uses a navigation drawer to switch between two fragments. However, each time I switch, the fragment is completely recreated.

相关标签:
10条回答
  • 2020-12-08 00:47

    Just find the current fragment calling getFragmentById("id of your container") and then hide it and show needed fragment.

    private void openFragment(Fragment fragment, String tag) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
            Fragment existingFragment = fragmentManager.findFragmentByTag(tag);
            if (existingFragment != null) {
                Fragment currentFragment = fragmentManager.findFragmentById(R.id.container);
                fragmentTransaction.hide(currentFragment);
                fragmentTransaction.show(existingFragment);
            }
            else {
                fragmentTransaction.add(R.id.container, fragment, tag);
            }
            fragmentTransaction.commit();
        }
    
    0 讨论(0)
  • 2020-12-08 00:48

    How about playing with the Visible attribute?

    0 讨论(0)
  • 2020-12-08 00:52

    After @meredrica pointed out that replace() destroys the fragments, I went back through the FragmentManager documentation. This is the solution I've come up with, that seems to be working.

    /* The click listener for ListView in the navigation drawer */
    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }
    
    private void selectItem(int position) {
        android.support.v4.app.FragmentManager; fragmentManager = getSupportFragmentManager();
    
        switch(position) {
            case 0:
                if(fragmentManager.findFragmentByTag("one") != null) {
                    //if the fragment exists, show it.
                    fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("one")).commit();
                } else {
                    //if the fragment does not exist, add it to fragment manager.
                    fragmentManager.beginTransaction().add(R.id.container, new OneFragment(), "one").commit();
                }
                if(fragmentManager.findFragmentByTag("two") != null){
                    //if the other fragment is visible, hide it.
                    fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("two")).commit();
                }
                break;
            case 1:
                if(fragmentManager.findFragmentByTag("two") != null) {
                    //if the fragment exists, show it.
                    fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("two")).commit();
                } else {
                    //if the fragment does not exist, add it to fragment manager.
                    fragmentManager.beginTransaction().add(R.id.container, new TwoFragment(), "two").commit();
                }
                if(fragmentManager.findFragmentByTag("one") != null){
                    //if the other fragment is visible, hide it.
                    fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("one")).commit();
                }
                break;
        }
    
        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        setTitle(mNavTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    }
    

    I also added this bit, but I'm not sure if it's necessary or not.

    @Override
    public void onDestroy() {
        super.onDestroy();
        FragmentManager fragmentManager = getSupportFragmentManager();
        if(fragmentManager.findFragmentByTag("one") != null){
            fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("one")).commit();
        }
        if(fragmentManager.findFragmentByTag("two") != null){
            fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("two")).commit();
        }
    }
    
    0 讨论(0)
  • 2020-12-08 00:52

    The replace method destroys your fragments. One workaround is to set them to Visibility.GONE, another (less easy) method is to hold them in a variable. If you do that, make sure you don't leak memory left and right.

    0 讨论(0)
  • 2020-12-08 00:53

    Same idea as Tester101 but this is what I ended up using.

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
        Fragment oldFragment = fragmentManager.findFragmentByTag( "" + m_lastDrawerSelectPosition );
        if ( oldFragment != null )
            fragmentTransaction.hide( oldFragment );
    
        Fragment newFragment = fragmentManager.findFragmentByTag( "" + position );
        if ( newFragment == null )
        {
            newFragment = getFragment( position );
            fragmentTransaction.add( R.id.home_content_frame, newFragment, "" + position );
        }
    
        fragmentTransaction.show( newFragment );
        fragmentTransaction.commit();
    
    0 讨论(0)
  • 2020-12-08 00:54

    Hide easily in kotlin using extensions:

    fun FragmentManager.present(newFragment: Fragment, lastFragment: Fragment? = null, containerId: Int) {
        if (lastFragment == newFragment) return
    
        val transaction = beginTransaction()
        if (lastFragment != null && findFragmentByTag(lastFragment.getTagg()) != null) {
            transaction.hide(lastFragment)
        }
    
        val existingFragment = findFragmentByTag(newFragment.getTagg())
        if (existingFragment != null) {
            transaction.show(existingFragment).commit()
        } else {
            transaction.add(containerId, newFragment, newFragment.getTagg()).commit()
        }
    }
    
    fun Fragment.getTagg(): String = this::class.java.simpleName
    

    Usage

    supportFragmentManager.present(fragment, lastFragment, R.id.fragmentPlaceHolder)
    lastFragment = fragment
    
    0 讨论(0)
提交回复
热议问题