IllegalStateException: фрагмент еще не был прикреплен при использовании BottomNavigation - PullRequest
0 голосов
/ 12 сентября 2018

Я использую BottomNavigationDrawer / BottomSheetDialog из в следующем примере , где BottomNavigationDrawer переключается между несколькими фрагментами внутри одного действия.

В то время как реализует BottomNavigationDrawer, я понял, что, когда фрагменты менялись местами без использования меню, то есть путем нажатия кнопки во фрагменте, это оставляло выбор меню в несогласованном состоянии. . Кроме того, решение использовать функцию в основной активности для запуска FragmentTransaction вызвало сбои.

public void resetNavDefault(){
        if(fragment == null) {
            fragment = new BottomNavigationDrawerFragment();
            navigationView = fragment.getNavigationView();
        } else navigationView = fragment.getNavigationView();
        //navigationView.getMenu().getItem(0).setChecked(true);
        Log.d(TAG, "resetNavDefault: setting check");
        MenuItem item = navigationView.getMenu().getItem(0);
        navigationView.getMenu().performIdentifierAction(item.getItemId(), 0);
    }

Я понял, что это было вызвано тем, что getSupportFragmentManager был нулевым и / или фрагмент не был прикреплен , а с использованием getChildFragmentManager не было правильным решением, как я не использовать вложенные фрагменты, только несколько фрагментов в одном упражнении.

Я также попытался реализовать этот обходной путь, где onDetach переопределяется, чтобы childFragmentManager был доступен .

Это исправление предотвращает сбой приложения с NPE (из-за условия if (!isAdded()) return;), но оставляет кнопку, которая запускает новый фрагмент, без ответа (кнопка не работает ).

Как перемещаться между двумя фрагментами, используя FragmentTransaction, не вызывая NPE и не оставляя пункт меню в несогласованном состоянии?

Моя BottomNavigationDrawer реализация выглядит следующим образом:

BottomNavigationDrawer

public class BottomNavigationDrawerFragment extends BottomSheetDialogFragment {

    BottomNavigationDrawerFragment fragment;
    public NavigationView navigationView;
    ImageView close, menu;
    Statuser statuser;
    RevivDatabase database;
    String email, fname, lname;
    TextView txtUsername, txtEmail;

    private static String TAG = "BottomNavDrawerFragment";

    public BottomNavigationDrawerFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment_bottomsheet, container, false);
        txtUsername = view.findViewById(R.id.txtUsername);
        txtEmail = view.findViewById(R.id.txtEmail);
        navigationView = view.findViewById(R.id.navigation_view);
        database = RevivDatabase.getDatabase(getActivity());
        statuser = database.revivDao().getUserDetails();
        fname = statuser.getFname();
        lname = statuser.getLname();
        email = statuser.getEmail();
        txtEmail.setText(email);
        txtUsername.setText(fname+" "+lname);
        setRetainInstance(true);
        close = view.findViewById(R.id.imgClose);
        fragment = this;
        close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fragment.dismiss();
            }
        });
        navigationView.setItemIconTintList(null);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                menuItem.setChecked(true);
                int id = menuItem.getItemId();
                FragmentManager manager;
                try {
                    manager = getActivity().getSupportFragmentManager();
                } catch (NullPointerException e) {
                    if (!isAdded()) return false;
                    manager = getChildFragmentManager();
                    Log.e(TAG, "onNavigationItemSelected: ", e);
                }
                switch (id){
                    case R.id.app_bar_incident:
                        navigationView.getMenu().findItem(id).setChecked(true);
                        manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivIncidentDashboard()).commit();
                        Toast.makeText(getContext(), "Request Incident", Toast.LENGTH_SHORT).show();
                        fragment.dismiss();
                        break;
                    case R.id.app_bar_housecall:
                        navigationView.getMenu().findItem(id).setChecked(true);
                        manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivHousecallDashboard()).commit();
                        fragment.dismiss();
                        Toast.makeText(getContext(), "Request Housecall", Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.settings:
                        navigationView.getMenu().findItem(id).setChecked(true);
                        manager.beginTransaction().replace(R.id.containerFrameLayout, new FragmentRevivSettingsMain()).commit();
                        Toast.makeText(getActivity().getApplicationContext(), "Settings", Toast.LENGTH_SHORT).show();
                        fragment.dismiss();
                        break;

                }
                return true;
            }
        });

        return view;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public NavigationView getNavigationView() {
        return navigationView;
    }
}

Мое сообщение об ошибке

09-13 00: 26: 32.996 28025-28025 / com.package.name E / AndroidRuntime: ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: главная Процесс: com.package.name, PID: 28025 java.lang.IllegalStateException: фрагмент еще не был прикреплен. на android.support.v4.app.Fragment.instantiateChildFragmentManager (Fragment.java:2386) на android.support.v4.app.Fragment.getChildFragmentManager (Fragment.java:842) в com.package.name.Fragments.BottomNavigationDrawerFragment $ 2.onNavigationItemSelected (BottomNavigationDrawerFragment.java:108) на android.support.design.widget.NavigationView $ 1.onMenuItemSelected (NavigationView.java:170) на android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected (MenuBuilder.java:840) на android.support.v7.view.menu.MenuItemImpl.invoke (MenuItemImpl.java:158) на android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:991) на android.support.v7.view.menu.MenuBuilder.performItemAction (MenuBuilder.java:981) на android.support.v7.view.menu.MenuBuilder.performIdentifierAction (MenuBuilder.java:977) в com.package.name.Reviv.resetNavDefault (Reviv.java:644) в com.package.name.Fragments.FragmentRevivSettingsMain $ 1.onClick (FragmentRevivSettingsMain.java:77) на android.view.View.performClick (View.java:6303) на android.view.View $ PerformClick.run (View.java:24828) на android.os.Handler.handleCallback (Handler.java:789) на android.os.Handler.dispatchMessage (Handler.java:98) на android.os.Looper.loop (Looper.java:164) на android.app.ActivityThread.main (ActivityThread.java:6798) в java.lang.reflect.Method.invoke (родной метод) на com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)

1 Ответ

0 голосов
/ 15 сентября 2018

Сначала реализуйте событие нажатия кнопки в вашей MainActivity, как на этой странице .Затем, если у вас есть экземпляр BottomNavigationDrawerFragment в MainActivity, просто получите представление через этот экземпляр и вызовите setSelection для меню навигации через это представление при нажатии кнопки.Убедитесь, что вы получаете представление через экземпляр после выполнения вызова bottomNavDrawerFragment.show (..).В противном случае вы получите ошибку NPE.

...