避免使用 BottomNavigationView 再次创建片段

Ser*_*o76 1 android android-fragments

我正在向我的应用程序添加一个包含三个片段的 BottomNavigationView。一切正常,除了一件事。

在第一个片段中,有一个 EditText 视图,在第二个片段中有一个 ListView,在第三个片段中,有一些从服务器中托管的 JSON 加载的文本和图像。

这是我的代码:

bottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
          @Override
          public boolean onNavigationItemSelected(@NonNull MenuItem item) {
              int id = item.getItemId();
              switch (id) {
                  case R.id.menu_dash:
                      fragment = new frg_dash();
                      break;
                  case R.id.menu_list:
                      fragment = new frg_list();
                      break;
                  case R.id.menu_info:
                      fragment = new frg_info();        
                      break;
              }
              final FragmentTransaction transaction = fragmentManager.beginTransaction();
              transaction.replace(R.id.contenedor_principal, fragment).commit();

              return true;
          }
      });
Run Code Online (Sandbox Code Playgroud)

问题是,每次我使用 bottomNavigationView 按钮从一个片段转到另一个片段时,该片段都会再次开始执行。

我正在寻找的结果是,例如,如果第二个片段中的用户位于 ListView 的中间,则它会转到第三个片段并再次返回,ListView 会继续原来的位置。或者如果在bottomNavigationView中按下第三个Fragment的按钮,不要再次从服务器加载数据。

我猜问题是当你点击一个 bottomNavigationView 按钮时,这个片段又被创建了:

 ... switch (id) {
      case R.id.menu_dash:
      fragment = new frg_dash();
      break; ...
Run Code Online (Sandbox Code Playgroud)

但这只是一个猜测。我想它可以用 onCreate、onActivityCreated 和 onCreateView 方法控制,但同样,它们只是我的假设。

我已经尝试过使用片段的 hide() 和 show() 参数,但没有成功......或者我没有很好地应用它

我非常感谢提前的帮助。

编辑

这是我目前的示例,其中包含与答案相关的所有部分:

public void replaceFragment(Fragment fragment, @Nullable Bundle bundle, boolean popBackStack, boolean findInStack) {

    Log.v("2134", "Dentro");

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    String tag = fragment.getClass().getName();
    Log.v("2134", "tag:" + tag);
    Fragment parentFragment;
    if (findInStack && fm.findFragmentByTag(tag) != null) {
        parentFragment = fm.findFragmentByTag(tag);
    } else {
        parentFragment = fragment;
    }
    // if user passes the @bundle in not null, then can be added to the fragment
    if (bundle != null) {
        parentFragment.setArguments(bundle);
    } else {
        parentFragment.setArguments(null);
    }
    // this is for the very first fragment not to be added into the back stack.
    if (popBackStack) {
        fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
    } else {
        ft.addToBackStack(parentFragment.getClass().getName() + "");
    }
    ft.replace(R.id.contenedor_principal, parentFragment, tag);
    ft.commit();
    fm.executePendingTransactions();
}

...

bottomNavigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.menu_panel:
                fragment = new frg_panel();
                break;
            case R.id.menu_promos:
                fragment = new frg_promociones();
                break;
            case R.id.menu_catalogo:
                fragment = new frg_catalogo();
                break;
        }

        replaceFragment(fragment, null, true, true);

        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)

Khe*_*raj 5

使用此代码打开您的片段。您的片段不会每次都创建。如果存在,它将从堆栈中获取相同的片段。

/**
     * replace or add fragment to the container
     *
     * @param fragment pass android.support.v4.app.Fragment
     * @param bundle pass your extra bundle if any
     * @param popBackStack if true it will clear back stack
     * @param findInStack if true it will load old fragment if found
     */
    public void replaceFragment(Fragment fragment, @Nullable Bundle bundle, boolean popBackStack, boolean findInStack) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        String tag = fragment.getClass().getName();
        Fragment parentFragment;
        if (findInStack && fm.findFragmentByTag(tag) != null) {
            parentFragment = fm.findFragmentByTag(tag);
        } else {
            parentFragment = fragment;
        }
        // if user passes the @bundle in not null, then can be added to the fragment
        if (bundle != null)
            parentFragment.setArguments(bundle);
        else parentFragment.setArguments(null);
        // this is for the very first fragment not to be added into the back stack.
        if (popBackStack) {
            fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        } else {
            ft.addToBackStack(parentFragment.getClass().getName() + "");
        }
        ft.replace(R.id.contenedor_principal, parentFragment, tag);
        ft.commit();
        fm.executePendingTransactions();
    }
Run Code Online (Sandbox Code Playgroud)

像使用它一样

更新 :

如果您的片段是主页或仪表板片段,则

Fragment f = new YourFragment();
replaceFragment(f, null, true, true); 
Run Code Online (Sandbox Code Playgroud)

除此以外

Fragment f = new YourFragment();
replaceFragment(f, null, false, true); 
Run Code Online (Sandbox Code Playgroud)

重要此代码不能替代在片段中保存所有状态或变量。此代码将很有用,因为它不会再次创建片段实例。

要保存片段中的所有状态和变量以备将来使用,请参阅此答案