问题
I'm writing an app using BottomNavigationView and Fragment for updating the layout programmatically.
I'm trying to use a Stack to allow the user to click back and return to the previous fragment. I had tried to use addToBackStack after inflating a new fragment but when back is pressed despite the layout is changing correctly the selected item menu does not change with it.
So I decided to create a custom stack of Fragment and change with setSelectedItemId the selected item but this operation makes the application crash. I used that a lot of time normally and I am not able to understand this behavior.
Thanks for the help.
public class MainActivity extends FragmentActivity {
private FragmentManager fm = getSupportFragmentManager();
private Logger logger = Logger.getLogger("global");
private BottomNavigationView bnv;
private CustomStack customStack = new CustomStack();
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Fragment centerFragment;
switch (item.getItemId()) {
case R.id.navigation_home:
centerFragment = new Fragment1();
replaceCenterLayoutFragment(centerFragment);
customStack.push(centerFragment);
return true;
case R.id.navigation_map:
centerFragment = new Fragment2();
bnv.setSelectedItemId(R.id.navigation_interest);
return true;
case R.id.navigation_interest:
centerFragment = new Fragment3();
replaceCenterLayoutFragment(centerFragment);
customStack.push(centerFragment);
return true;
case R.id.navigation_notifications:
centerFragment = new Fragment4();
replaceCenterLayoutFragment(centerFragment);
customStack.push(centerFragment);
return true;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bnv = (BottomNavigationView) findViewById(R.id.navigation);
bnv.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
FragmentTransaction ft1 = fm.beginTransaction();
Board b = new Board();
ft1.add(R.id.center_layout, new Fragment1()).commit();
customStack.push(b);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
customStack.pop();
replaceCenterLayoutFragment(customStack.top());
}
return false;
}
private void replaceCenterLayoutFragment(Fragment f){
FragmentTransaction ft1 = fm.beginTransaction();
ft1.replace(R.id.center_layout, f).commit();
syncMenuItem(f);
}
private void syncMenuItem(Fragment f){
if(f instanceof Fragment1)
bnv.setSelectedItemId(R.id.p1);
if(f instanceof Fragment2)
bnv.setSelectedItemId(R.id.p2);
if(f instanceof Fragment3)
bnv.setSelectedItemId(R.id.p3);
if(f instanceof Fragment4)
bnv.setSelectedItemId(R.id.p4);
}
}
this is my custom stack
public class CustomStack {
private ArrayList<Fragment> menu ;
private Logger logger = Logger.getLogger("global");
public CustomStack(){
menu = new ArrayList<>();
}
public void push(Fragment i){
menu.add(i);
}
public Fragment pop (){
if(menu.size() > 0) {
int s = menu.size() -1;
Fragment app = menu.get(s);
menu.remove(s);
return app;
}
else{
return null;
}
}
public Fragment top(){
if(menu.size() > 0)
return menu.get(menu.size() -1);
else
return null;
}
public boolean isEmpty(){
return menu.size() > 0;
}
}
and the LogCatPage
07-10 20:31:07.879 28384-28384/? I/art: Late-enabling -Xcheck:jni
07-10 20:31:07.970 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_dependencies_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_dependencies_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.145 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_0_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_0_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.187 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_1_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_1_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.224 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_2_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_2_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.264 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_3_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_3_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.311 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_4_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_4_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.347 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_5_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_5_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.387 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_6_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_6_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.427 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_7_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_7_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.463 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_8_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_8_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.508 28384-28384/com.example.longsky.peoople W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.longsky.peoople-2/split_lib_slice_9_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.longsky.peoople-2@split_lib_slice_9_apk.apk@classes.dex) because non-0 exit status
07-10 20:31:08.509 28384-28384/com.example.longsky.peoople W/System: ClassLoader referenced unknown path: /data/app/com.example.longsky.peoople-2/lib/arm64
07-10 20:31:08.512 28384-28384/com.example.longsky.peoople I/InstantRun: starting instant run server: is main process
07-10 20:31:08.600 28384-28384/com.example.longsky.peoople W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
07-10 20:31:08.655 28384-28499/com.example.longsky.peoople E/AbstractTracker: Can't create handler inside thread that has not called Looper.prepare()
07-10 20:31:08.655 28384-28499/com.example.longsky.peoople D/AppTracker: App Event: start
07-10 20:31:08.661 28384-28501/com.example.longsky.peoople D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
07-10 20:31:08.679 28384-28501/com.example.longsky.peoople I/Adreno: QUALCOMM build : 183c040, Iff84fb1103
Build Date : 03/18/16
OpenGL ES Shader Compiler Version: XE031.06.00.02
Local Branch :
Remote Branch : refs/tags/AU_LINUX_ANDROID_LA.BF64.1.2.2_RB4.06.00.01.180.031
Remote Branch : NONE
Reconstruct Branch : NOTHING
07-10 20:31:08.686 28384-28501/com.example.longsky.peoople I/OpenGLRenderer: Initialized EGL, version 1.4
07-10 20:31:10.516 28384-28384/com.example.longsky.peoople D/AndroidRuntime: Shutting down VM
07-10 20:31:10.592 28384-28384/com.example.longsky.peoople E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.longsky.peoople, PID: 28384
java.lang.StackOverflowError: stack size 8MB
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.d
07-10 20:31:10.594 28384-28384/com.example.longsky.peoople D/AppTracker: App Event: crash
07-10 20:31:10.638 28384-28384/com.example.longsky.peoople D/Error: ERR: exClass=java.lang.StackOverflowError
07-10 20:31:10.638 28384-28384/com.example.longsky.peoople D/Error: ERR: exMsg=stack size 8MB
07-10 20:31:10.638 28384-28384/com.example.longsky.peoople D/Error: ERR: file=MainActivity.java
07-10 20:31:10.638 28384-28384/com.example.longsky.peoople D/Error: ERR: class=com.example.longsky.peoople.MainActivity
07-10 20:31:10.638 28384-28384/com.example.longsky.peoople D/Error: ERR: method=replaceCenterLayoutFragment line=96
07-10 20:31:10.647 28384-28384/com.example.longsky.peoople D/Error: ERR: stack=java.lang.StackOverflowError: stack size 8MB
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigationView.java:184)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969)
at android.support.design.widget.BottomNavigationView.setSelectedItemId(BottomNavigationView.java:341)
at com.example.longsky.peoople.MainActivity.replaceCenterLayoutFragment(MainActivity.java:96)
at com.example.longsky.peoople.MainActivity.access$000(MainActivity.java:15)
at com.example.longsky.peoople.MainActivity$1.onNavigationItemSelected(MainActivity.java:39)
at android.support.design.widget.BottomNavigationView$1.onMenuItemSelected(BottomNavigati
07-10 20:31:10.647 28384-28384/com.example.longsky.peoople D/Error: ERR: TOTAL BYTES WRITTEN: 862560
07-10 20:31:10.695 28384-28384/com.example.longsky.peoople I/Process: Sending signal. PID: 28384 SIG: 9
回答1:
The problem is that you setSelectedItemId
calls the listener, which will call replaceCenterLayoutFragment
, which will call setSelectedItemId
, and so on.
A hacky fix would be the following
private void replaceCenterLayoutFragment(Fragment f){
FragmentTransaction ft1 = fm.beginTransaction();
ft1.replace(R.id.center_layout, f).commit();
bnv.setOnNavigationItemSelectedListener(null);
syncMenuItem(f);
bnv.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
回答2:
For anbody else stumbling across this problem. If you select the navigation item through the menu, the listener doesn't get called:
bottomNavBar.getMenu().findItem(R.id.action_open_map).setChecked(true);
回答3:
I have found a much simpler solution. BottomNavigation has another listner called
setOnNavigationItemReselectedListener
Just override that listener and leave the method body empty.
bottomNavigationView.setOnNavigationItemReselectedListener(new BottomNavigationView.OnNavigationItemReselectedListener() {
@Override
public void onNavigationItemReselected(@NonNull MenuItem menuItem) {
return;
}
});
Explanation:
My guess is the setSelectedItemId same as before calls the listener, which will call replaceCenterLayoutFragment which will again call setSelectedItemId, but this time as it already called the normal SelectedListener, so it will call the ReselectedListener.
NavigationItemReselectedListener then just returns void and ends the loop of method calling.
来源:https://stackoverflow.com/questions/45018179/bottomnavigationview-setselecteditemid-crash