安卓导航抽屉碎片状态

14

目前我正在使用 Navigation Drawer 来开发我的 Android 应用。在第一个碎片中,我使用 Facebook 的 Graph API 加载数据。因此,当我的应用程序首次加载时,它会首先进入第一个碎片。

First

然后,我使用 Navigation Drawer 点击另一个 Fragment 并查看它。

Second Fragment

最后,我再次使用 Navigation Drawer 返回第一个 Fragment 并查看它。

First Fragment

我的问题是,如何继续利用已经创建的 Fragment,而不是在选择导航抽屉项时重新创建它。下面是我切换 Fragment 的代码。

private void displayView(int position) {
    // update the main content by replacing fragments
    Fragment fragment = null;
    switch (position) {
    case 0:
        fragment = new SelectionFragment();
        break;
    case 1:
        fragment = new HomeFragment();
        break;
    case 2:
        fragment = new PhotosFragment();
        break;
    case 3:
        fragment = new CommunityFragment();
        break;
    case 4:
        fragment = new PagesFragment();
        break;
    case 5:
        fragment = new SplashFragment();
        break;
    default:
        break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.frame_container, fragment).commit();

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(navMenuTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    } else {
        // error in creating fragment
        Log.e("MainActivity", "Error in creating fragment");
    }
}

我注意到每次选择选项时确实会有一个“新”的Fragment实例。我该如何实现创建Fragment实例的逻辑仅一次并重复使用它,以便我不必反复加载Fragment。


你有没有看到过用FragmentStatePagerAdapter替换ArrayAdapter的特定方法?我也在想同样的问题,但实际上并没有看到有人这样做,我也没有(我懒得尝试,不是因为不可能)。 - EpicPandaForce
4个回答

18

对于遇到与我相同问题的任何人,我已经找到了解决方案。

在容器框架中,我需要定义特定的片段视图,如下所示:

Specific fragments

在每个碎片视图中,我需要通过"android:name"属性将其与实际的碎片本身进行“链接”,如下所示。请注意碎片的路径,例如在我的情况下为com.example.confesssionsrp.SelectionFragment

<fragment
    android:id="@+id/selectionFragment"
    android:name="com.example.confessionsrp.SelectionFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
在MainActivity(或我们查看片段的Activity)中按照下面所示为每个Fragment创建变量。 Variables 接着,在MainActivity(或您特定的Activity)的Oncreate中,按照下面所示初始化各个Fragment。 OnCreate 然后创建一个名为“ShowFragment”的新方法,如下所示。
private void showFragment(int fragmentIndex, boolean addToBackStack) {
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    for (int i = 0; i < fragments.length; i++) {
        if (i == fragmentIndex) {
            transaction.show(fragments[i]);
            if (Session.getActiveSession().isClosed()) {
                mDrawerLayout
                        .setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            }
        } else {
            transaction.hide(fragments[i]);
        }
    }
    if (addToBackStack) {
        transaction.addToBackStack(null);
    }
    transaction.commit();
}
从那时起,在更换片段时,手动调用带有所选片段的“ShowFragment”方法,如下所示。

显示片段

总体上做所有这些,不会在每次查看它时重置片段,因此是答案的解决方案。感谢到目前为止帮助我的任何人 :)!

你的解决方案看起来非常好,我现在正在尝试它……我会点赞的。 :) - iamcrypticcoder
2
我们通过创建所有的片段来使应用程序变得沉重了,不是吗? - rakesh kashyap

0
我正在使用以下代码:
@Override
public void onNavigationDrawerItemSelected(int position) {

    // update the main content by replacing fragments
    FragmentManager fragmentManager = getFragmentManager();
    if(position==0){// selection of tabs content
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                SimulatorFragment.newInstance(position + 1)).commit();
    }else if(position==1){
        fragmentManager
        .beginTransaction()
        .replace(R.id.container,
                HudFragment.newInstance(position + 1)).commit();
    }else if(position==2){
        // Display the fragment as the main content.
        fragmentManager
        .beginTransaction()
        .replace(R.id.container, 
                SettingsBasicFragment.newInstance(position +1)).commit();
    }else{

    }
}

您可以在第一次替换时使用新实例并存储片段,如果不为空,则替换为存储的片段。

活动必须实现NavigationDrawerFragment.NavigationDrawerCallbacks接口

片段构造函数和newInstance方法如下:

public final class HudFragment extends Fragment {
/**
 * The fragment argument representing the section number for this
 * fragment.
 */
private static final String ARG_SECTION_NUMBER = "section_number";

/**
 * Returns a new instance of this fragment for the given section number.
 * @param simulation 
 */
public static HudFragment newInstance(int sectionNumber) {  
    HudFragment fragment = new HudFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    fragment.setArguments(args);
    return fragment;
}

public HudFragment() {
}

为了通过代码切换片段,我在NavigationDrawerFragment中使用了这个方法:

/**
 * Select a different section
 * @param position
 */
public void select(int position){
    selectItem(position);
}

private void selectItem(int position) {
    mCurrentSelectedPosition = position;
    if (mDrawerListView != null) {
        mDrawerListView.setItemChecked(position, true);
    }            
    if (mDrawerLayout != null) {
        mDrawerLayout.closeDrawer(mFragmentContainerView);
    }
    if (mCallbacks != null) {
        mCallbacks.onNavigationDrawerItemSelected(position);
    }
}

嘿,感谢你的帮助!我非常感激。但是我已经找到了另一种更简单的实现方式。再次感谢你的帮助,伙计! :) - Arvind Dinivra

0

第二个选项是从Android SDK提供的navigationDrawer示例开始。在创建项目时,我选择了该活动模板,几乎所有先前答案的代码都是自动生成的。

如果您想在设备旋转或类似情况下保留片段,则需要保留片段。否则,您只需要将片段的新实例保存在变量中,并检查它是否为空以创建一个新实例或使用旧实例。


0
如果有人想采用不同的方法,可以在栈上找到该片段:
// check if this fragment is on the backstack to avoid creating a new one
    Fragment foundFragment =  fragmentManager.findFragmentByTag("unique_fragment_tag");
    if (foundFragment != null) {
          fragmentManager.popBackStackImmediate("unique_fragment_tag", 0);
            return;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接