web-dev-qa-db-fra.com

État des fragments du tiroir de navigation Android

J'utilise actuellement le tiroir de navigation pour mon application Android. Dans mon premier fragment, j'ai un fragment qui charge des données à l'aide de l'API graphique de Facebook. Ainsi, lorsque mon application est chargée pour la première fois, elle passe d'abord au premier fragment.

First

Ensuite, j'utilise le tiroir de navigation pour cliquer sur un autre fragment et le visualiser.

Second Fragment

Et puis finalement, je réutilise le tiroir de navigation pour revenir au premier fragment et le visualiser.

First Fragment

Mon problème auquel je suis confronté est de savoir comment utiliser le fragment créé une fois au lieu de le recréer chaque fois que l'élément du tiroir de navigation est sélectionné. Mon code pour la commutation des fragments est comme indiqué ci-dessous.

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");
    }
}

J'ai remarqué qu'il y a effectivement une "nouvelle" instance du fragment à chaque fois que l'option est sélectionnée. Comment puis-je implémenter la logique de création de l'instance de FragmentUNE FOISet de la réutiliser, de sorte que je n'ai pas à charger le Fragment continuellement.

14
Arvind Dinivra

Pour tous ceux qui rencontrent le même problème avec moi, j'ai réussi à trouver une solution.

Dans le cadre du conteneur, je dois définir des vues de fragment spécifiques que je vais utiliser comme indiqué ci-dessous.

Specific fragments

Dans chaque vue Fragment, je dois la "lier" avec le fragment lui-même comme indiqué ci-dessous via l'attribut "Android: nom". Prenez note du chemin à le fragment, par exemple dans mon cas, il s'agit de 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" />

Dans la MainActivity (ou l'activité dans laquelle nous visionnons les fragments), créez des variables pour chacun des fragments, comme indiqué ci-dessous.

Variables

Ensuite, dans le Oncreate de MainActivity (ou de votre activité spécifique), initialisez les divers fragments comme indiqué ci-dessous.

OnCreate

Continuez à créer une nouvelle méthode appelée "ShowFragment _" comme indiqué ci-dessous.

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();
}

A partir de là, lors de la commutation des fragments, appelez manuellement la méthode "ShowFragment" avec le fragment sélectionné, comme indiqué ci-dessous.

Show Fragment

Faire tout cela dans son ensemble, ne réinitialisera pas le fragment à chaque fois que nous le verrons, et constitue donc la solution à la réponse. Merci à tous ceux qui m'ont aidé jusqu'à présent :)!

17
Arvind Dinivra

Au cas où quelqu'un voudrait avoir une approche différente: vous pourriez trouver le fragment sur la pile:

// 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;
    }
0
aarcoraci

La deuxième option consiste à commencer par l'exemple de navigationDrawer proposé par le SDK Android. J'ai sélectionné ce modèle d'activité lors de la création du projet et la quasi-totalité du code de ma réponse précédente est produite automatiquement. 

Si vous souhaitez conserver les fragments après une rotation de périphérique ou des éléments similaires, il en va autrement, vous devez alors conserver les fragments. Sinon, il vous suffit de sauvegarder la nouvelle instance du fragment dans une variable et de vérifier si elle est nulle pour en créer une nouvelle ou utiliser l'ancienne.

0
XaviGG

J'utilise le code suivant:

@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{

    }
}

Vous pouvez remplacer la première fois par une nouvelle instance et stocker le fragment. S'il n'est pas null, remplacez-le par le fragment stocké.

L'activité doit implémenter NavigationDrawerFragment.NavigationDrawerCallbacks

Le constructeur de fragments et les méthodes newInstance se présentent comme suit:

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() {
}

Pour changer de fragments par code, j'utilise cette méthode dans le 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);
    }
}
0
XaviGG