Android IllegalStateException:使用BottomNavigation时尚未附加片段
我使用的是来自的Android IllegalStateException:使用BottomNavigation时尚未附加片段,android,android-fragments,navigation-drawer,navigationview,Android,Android Fragments,Navigation Drawer,Navigationview,我使用的是来自的BottomNavigationDrawer/BottomSheetDialog,其中BottomNavigationDrawer在单个活动内的多个片段之间切换 然而,我意识到,当在不使用菜单的情况下交换片段时,即通过单击片段中的按钮,使用主活动中的函数触发FragmentTransaction的解决方案也会导致崩溃 public void resetNavDefault(){ if(fragment == null) { fragment
BottomNavigationDrawer
/BottomSheetDialog
,其中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
为null造成的,这不是正确的解决方案,因为我不使用嵌套片段,只在单个活动中使用多个片段
我还尝试在何处实施此解决方案
(由于if(!isAdded())返回;
条件),但启动新片段的按钮没有响应(按钮不工作)
如何使用FragmentTransaction
在两个片段之间导航,而不会导致NPE,也不会使菜单选择处于不一致的状态
我的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.InstanceChildFragmentManager(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.menuitemmpl.invoke(menuitemmpl.java:158)中
位于android.support.v7.view.menu.MenuBuilder.performitemation(MenuBuilder.java:991)
位于android.support.v7.view.menu.MenuBuilder.performitemation(MenuBuilder.java:981)
位于android.support.v7.view.menu.MenuBuilder.performIdentifierAction(MenuBuilder.java:977)
位于com.package.name.revio.resetNavDefault(revo.java:644)
位于com.package.name.Fragments.fragmentRevivationSettingsMain$1.onClick(fragmentRevivationSettingsMain.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)
首先在MainActivity中实现按钮单击事件,如下所示。然后假设在MainActivity中有BottomNavigationDrawerFragment实例,只需通过该实例获取视图,并在单击按钮时通过该视图调用setSelection导航菜单。确保在发出bottomNavDrawerFragment.show(..)调用后通过实例获取视图。否则您将出现NPE错误。非常感谢您,费拉特。我尝试了您建议的解决方案,但最终决定在单击按钮时创建BottomNavFragment的新实例,并在创建后设置选择。这是非常粗糙的,但我想我可以把代码拿出来,并在代码发布后开发更全面的解决方案。(这是测试版)。我将发布一个更新,一旦我实现了你的解决方案,希望很快。我接受你的回答,因为我确信它会起作用。不客气,我希望它能有所帮助。请随时评论进一步的更新。