简体   繁体   English

BottomNavigationView 在每次点击选项卡时创建新片段(android.os.TransactionTooLargeException)

[英]BottomNavigationView creates new fragment with every click on tab (android.os.TransactionTooLargeException)

I have a BottomNavigationView with 5 items.我有一个包含 5 个项目的 BottomNavigationView。 Sometimes I got error android.os.TransactionTooLargeException.有时我收到错误 android.os.TransactionTooLargeException。

I used TooLargeTool to find a problem and found out that it happens when app goes background if I click on tabs many time because every time a new fragment created and finally data parcel size becomes more than 1 mb which generates an exception.我使用 TooLargeTool 发现了一个问题,发现如果我多次单击选项卡,当应用程序进入后台时会发生这种情况,因为每次创建新片段并且最终数据包大小都会超过 1 mb,从而生成异常。

      val navController = findNavController(R.id.nav_host_fragment_activity_main)




          WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = false


    navController.addOnDestinationChangedListener { _, destination, _ ->
        when (destination.id){
            R.id.rifleChoiceFragment -> {
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
            }
            R.id.ammoChoiceFragment -> {
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
            }
            R.id.dataBaseFragment-> {
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
            }
            R.id.caliberChoiceFragment-> {
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
            }
            R.id.vendorChoiceFragment-> {
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
            }
            R.id.secondAmmoChoiceFragment-> {
                navView.visibility = View.GONE
                window.statusBarColor = defaultColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
            }
            R.id.payWallFragment -> {
                navView.visibility = View.GONE
                window.statusBarColor = blackColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = false
            }
            R.id.splashFragment-> {
                navView.visibility = View.GONE
                window.statusBarColor = blackColor
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = false
            }
            else -> {
                WindowInsetsControllerCompat(window,window.decorView).isAppearanceLightStatusBars = true
                navView.visibility = View.VISIBLE
                window.statusBarColor = defaultColor
            }
        }


    }
    navView.setupWithNavController(navController)

nav graph:导航图:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/splashFragment">

<fragment
    android:id="@+id/navigation_home"
    android:name="NAME"
    android:label="@string/title_home"
    tools:layout="@layout/fragment_ammo" >
    <action
        android:id="@+id/action_navigation_home_to_rifleChoiceFragment"
        app:destination="@id/rifleChoiceFragment"
        app:launchSingleTop="false" />
    <action
        android:id="@+id/action_navigation_home_to_ammoChoiceFragment"
        app:destination="@id/ammoChoiceFragment"
        app:launchSingleTop="false" />
</fragment>

<fragment
    android:id="@+id/navigation_dashboard"
    android:name="NAME"
    android:label="@string/title_dashboard"
    tools:layout="@layout/fragment_table" />

<fragment
    android:id="@+id/navigation_notifications"
    android:name="NAME"
    android:label="@string/Trajectory"
    tools:layout="@layout/fragment_plot" >
    <action
        android:id="@+id/action_navigation_notifications_to_secondAmmoChoiceFragment"
        app:destination="@id/secondAmmoChoiceFragment"
        app:launchSingleTop="false" />
</fragment>
<fragment
    android:id="@+id/navigation_target"
    android:name="NAME"
    android:label="@string/reticle"
    tools:layout="@layout/fragment_target" >
    <action
        android:id="@+id/action_navigation_target_to_reticleChoiceFragment"
        app:destination="@id/reticleChoiceFragment"
        app:launchSingleTop="false" />
    <action
        android:id="@+id/action_navigation_target_to_targetChoiceFragment"
        app:destination="@id/targetChoiceFragment"
        app:launchSingleTop="false" />
    <action
        android:id="@+id/action_navigation_target_to_payWallFragment"
        app:destination="@id/payWallFragment"
        app:launchSingleTop="true" />
</fragment>
<fragment
    android:id="@+id/navigation_settings"
    android:name="NAME t"
    android:label="@string/settings"
    tools:layout="@layout/settings_fragment" />
<fragment
    android:id="@+id/rifleChoiceFragment"
    android:name="NAME"
    android:label="rifle_choice_fragment"
    tools:layout="@layout/rifle_choice_fragment" />
<fragment
    android:id="@+id/ammoChoiceFragment"
    android:name="NAME"
    android:label="fragment_ammo_choice"
    tools:layout="@layout/fragment_ammo_choice" >
    <action
        android:id="@+id/action_ammoChoiceFragment_to_dataBaseFragment"
        app:destination="@id/dataBaseFragment"
        app:launchSingleTop="false" />
</fragment>
<fragment
    android:id="@+id/dataBaseFragment"
    android:name="NAME"
    android:label="fragment_data_base"
    tools:layout="@layout/fragment_data_base" >
    <action
        android:id="@+id/action_dataBaseFragment_to_caliberChoiceFragment"
        app:destination="@id/caliberChoiceFragment"
        app:launchSingleTop="false" />
    <action
        android:id="@+id/action_dataBaseFragment_to_vendorChoiceFragment"
        app:destination="@id/vendorChoiceFragment"
        app:launchSingleTop="false" />
</fragment>
<fragment
    android:id="@+id/caliberChoiceFragment"
    android:name="NAME"
    android:label="fragment_caliber_choice"
    tools:layout="@layout/fragment_caliber_choice" />
<fragment
    android:id="@+id/vendorChoiceFragment"
    android:name="NAME"
    android:label="fragment_vendor_choice"
    tools:layout="@layout/fragment_vendor_choice" />
<fragment
    android:id="@+id/secondAmmoChoiceFragment"
    android:name="NAME"
    android:label="fragment_second_ammo_choice"
    tools:layout="@layout/fragment_second_ammo_choice" >
    <action
        android:id="@+id/action_secondAmmoChoiceFragment_to_dataBaseFragment"
        app:destination="@id/dataBaseFragment" />
</fragment>
<fragment
    android:id="@+id/reticleChoiceFragment"
    android:name="NAME"
    android:label="fragment_reticle_choice"
    tools:layout="@layout/fragment_reticle_choice" />
<fragment
    android:id="@+id/targetChoiceFragment"
    android:name="NAME"
    android:label="fragment_target_choice"
    tools:layout="@layout/fragment_target_choice" />
<fragment
    android:id="@+id/payWallFragment"
    android:name="NAME"
    android:label="fragment_pay_wall"
    tools:layout="@layout/fragment_pay_wall" >
    <action
        android:id="@+id/action_payWallFragment_to_navigation_home"
        app:destination="@id/navigation_home"
        app:launchSingleTop="false"
        app:popUpTo="@id/mobile_navigation"
        app:popUpToInclusive="true" />
</fragment>
<fragment
    android:id="@+id/splashFragment"
    android:name="NAME"
    android:label="fragment_splash"
    tools:layout="@layout/fragment_splash" >
    <action
        android:id="@+id/action_splashFragment_to_navigation_home"
        app:destination="@id/navigation_home"
        app:launchSingleTop="false"
        app:popUpTo="@id/mobile_navigation"
        app:popUpToInclusive="true" />
    <action
        android:id="@+id/action_splashFragment_to_payWallFragment"
        app:destination="@id/payWallFragment"
        app:launchSingleTop="false"
        app:popUpTo="@id/mobile_navigation"
        app:popUpToInclusive="true" />
</fragment>


</navigation>

bottom nav menu:底部导航菜单:

<?xml version="1.0" encoding="utf-8"?>
<item
    android:id="@+id/navigation_home"
    android:icon="@drawable/ic_bulletsvg"
    android:title="@string/title_home" />

<item
    android:id="@+id/navigation_dashboard"
    android:icon="@drawable/ic_spreadsheet"
    android:title="@string/title_dashboard"
   />

<item
    android:id="@+id/navigation_notifications"
    android:icon="@drawable/ic_b"
    android:title="@string/Trajectory"
    />
<item
    android:id="@+id/navigation_targ"
    android:icon="@drawable/ic_ret"
    android:title="@string/ret"
    />

<item
    android:id="@+id/navigation_settings"
    android:icon="@drawable/ic_set"
    android:title="@string/settings"
    />

What's the proper way to fix it?修复它的正确方法是什么? Should I handle click on each tab manually?我应该手动处理每个选项卡上的点击吗?

This is your problem:这是你的问题:

app:startDestination="@+id/splashFragment"

As per the Principles of Navigation , you should be using your actual home screen as the start destination of your graph:根据Principles of Navigation ,您应该使用实际的主屏幕作为图表的起始目的地:

app:startDestination="@+id/navigation_home"

You should never be using a splash destination as your start destination - as per those exact same principles:你永远不应该使用启动目标作为你的起始目标——根据这些完全相同的原则:

Note: An app might have a one-time setup or series of login screens.注意:应用程序可能具有一次性设置或一系列登录屏幕。 These conditional screens should not be considered start destinations because users see these screens only in certain cases.这些条件屏幕不应被视为起始目的地,因为用户仅在某些情况下才会看到这些屏幕。

This is how you should be implementing your paywall screen - by following the Conditional Navigation documentation to conditionally navigate from your actual start destination to the paywall screen.这就是您应该如何实现您的付费专区屏幕——按照条件导航文档有条件地从您的实际起始目的地导航到付费专区屏幕。

Why is this the source of the problem with your bottom navigation?为什么这是底部导航问题的根源? It is because setupByNavController pops up to the start destination of your app when swapping between tabs, thus ensuring that each tab is independent from one another.这是因为在选项卡之间切换时, setupByNavController弹出应用程序的起始目的地,从而确保每个选项卡彼此独立。 When the start destination of your app isn't on the back stack, there is no single point of reference in the back stack to know what to pop up to so what happens is that nothing gets popped at all - you just keep building up more and more and more of a back stack instead of replacing one back stack with another as you swap tabs.当您的应用程序的起始目的地不在返回堆栈上时,返回堆栈中没有单一的参考点来知道要弹出什么,所以发生的是什么都不会弹出 - 您只是不断地建立更多以及越来越多的后退堆栈,而不是在交换选项卡时将一个后退堆栈替换为另一个后退堆栈。 By keeping the start destination of your app on the back stack, setupWithNavController , which assumes you are following the Principles of Navigation, will work as intended.通过将应用程序的起始目的地保留在返回堆栈中,假定您遵循导航原则的setupWithNavController将按预期工作。

You'll find that using a splash screen for your start destination also breaks any deep links you add to your graph as it is the start destination that is added to the back stack and you want your home screen to be on the back stack, not your splash screen.您会发现,为您的起始目的地使用启动画面也会破坏您添加到图形中的任何深层链接,因为它是添加到后退堆栈的起始目的地,并且您希望您的主屏幕位于后退堆栈上,而不是你的闪屏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从 Fragment 移动到 Activity 导致 android.os.TransactionTooLargeException - Move from Fragment to Activity Causes android.os.TransactionTooLargeException android.os.TransactionTooLargeException检索已安装的应用程序 - android.os.TransactionTooLargeException retrieving installed applications 执行queryIntentActivities时android.os.TransactionTooLargeException - android.os.TransactionTooLargeException when executing queryIntentActivities 碎片化newInstance保存到捆绑的太多数据-android.os.TransactionTooLargeException - Fragment newInstance too much data saved to bundle - android.os.TransactionTooLargeException android.os.TransactionTooLargeException:数据包大小NOUGAT错误 - android.os.TransactionTooLargeException: data parcel size NOUGAT ERROR android.app.DialogFragment.onStart上的android.os.TransactionTooLargeException - android.os.TransactionTooLargeException at android.app.DialogFragment.onStart 由于java.lang.RuntimeException而在图库中崩溃:android.os.TransactionTooLargeException:数据包大小539544字节 - Crash in gallery due to java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 539544 bytes 在AsyncTask中使用Gson编写/读取JSON时发生android.os.TransactionTooLargeException - android.os.TransactionTooLargeException occurs when Writing/Reading JSON with Gson in AsyncTask Android Studio BottomNavigationView显示片段 - Android Studio BottomNavigationView show fragment 片段上的底部导航视图 - BottomNavigationView on fragment
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM