Android: Fragment has null arguments when getting global nested safeargs

1.7k Views Asked by At

I am trying to get my safeargs within the second fragment (calibrateRepairOptionFragment) of my nested_graph, The problem is that I get the above written error Fragment CalibrateRepairOptionFragment{5e1268d} (c7c2906d-5a17-4d22-b41d-eefe8eee059f) id=0x7f09012d} has null arguments.

I am confused because when I try to get my safeargs in the first fragment (CalibrateRepairMessageFragment), everything works and the toolbar_title is not null.

BaseFragment (getting safeargs here)

abstract class NewBaseEmailFragment<out VB: ViewDataBinding>(
    private val layout: Int,
    private val next: Int,
) : Fragment(layout) {
    abstract val viewModel: ViewModel
    private val toolbarTitleArgs by navArgs<NavSendEmailArgs>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = DataBindingUtil.inflate<VB>(inflater, layout, container, false).apply {
        lifecycleOwner = viewLifecycleOwner
        setVariable(BR.viewModel, viewModel)
    }.root

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initToolbar()
    }

    // Using safeargs here, everything fine in the first fragment of the nested graph
    private fun initToolbar() = with(toolbar) {
        setupWithNavController(findNavController(), AppBarConfiguration(findNavController().graph))
        toolbar_title.text = toolbarTitleArgs.toolbarTitle
    }
}

First Fragment (no error here, toolbar is set correctly)

@AndroidEntryPoint
class CalibrateRepairMessageFragment : NewBaseEmailFragment<FragmentCalibrateRepairUserDataBinding>(
    R.layout.fragment_calibrate_repair_message,
    R.id.action_calibrateRepairMessageFragment_to_calibrateRepairOptionFragment,
 ) {
    override val viewModel: EmailViewModel by navGraphViewModels(R.id.nav_send_email) { defaultViewModelProviderFactory }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    }
}

Second Fragment (getting error here, toolbar.title is null)

@AndroidEntryPoint
class CalibrateRepairOptionFragment : NewBaseEmailFragment<FragmentCalibrateRepairOptionBinding>(
    R.layout.fragment_calibrate_repair_option,
    R.id.action_calibrateRepairOptionFragment_to_calibrateRepairUserDataFragment,
) {
    override val viewModel: EmailViewModel by navGraphViewModels(R.id.nav_send_email) { defaultViewModelProviderFactory }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
    }
}

nav_main.xml

<!-- Sending arguments from homeFragment to nested Graph "nav_send_email" -->
<fragment
    android:id="@+id/homeFragment"
    android:name="com.example.app.framework.ui.view.fragments.home.HomeFragment"
    tools:layout="@layout/fragment_home">

    <action
        android:id="@+id/action_homeFragment_to_nav_send_email"
        app:destination="@id/nav_send_email">
    </action>
</fragment>
<!-- NESTED GRAPH "nav_send_mail" --->
<navigation
    android:id="@+id/nav_send_email"
    app:startDestination="@id/calibrateRepairMessageFragment">
    <!-- Global argument for entire nested graph -->
    <argument
        android:name="toolbar_title"
        app:argType="string"
        app:nullable="false" />

    <!-- Getting safeargs here is no problem! (first fragment) -->
    <fragment
        android:id="@+id/calibrateRepairMessageFragment"
        android:name="com.example.app.framework.ui.view.fragments.home.calibrateAndRepair.CalibrateRepairMessageFragment"
        tools:layout="@layout/fragment_calibrate_repair_message">
        <argument
            android:name="toolbar_title"
            app:argType="string"
            app:nullable="false" />
        <action
            android:id="@+id/action_calibrateRepairMessageFragment_to_calibrateRepairOptionFragment"
            app:destination="@id/calibrateRepairOptionFragment" />
    </fragment>

    <!-- Can't get safeargs here, safeargs is null (second fragment) -->
    <fragment
        android:id="@+id/calibrateRepairOptionFragment"
        android:name="com.example.app.framework.ui.view.fragments.home.calibrateAndRepair.CalibrateRepairOptionFragment"
        tools:layout="@layout/fragment_calibrate_repair_data_overview">
        <action
            android:id="@+id/action_calibrateRepairOptionFragment_to_calibrateRepairUserDataFragment"
            app:destination="@id/calibrateRepairUserDataFragment" />
    </fragment>
   
</navigation>

Full Stracktrace

 java.lang.IllegalStateException: Fragment CalibrateRepairOptionFragment{5e1268d} (c7c2906d-5a17-4d22-b41d-eefe8eee059f) id=0x7f09012d} has null arguments
        at com.example.app.framework.ui.view.fragments.home.refactor.NewBaseEmailFragment$$special$$inlined$navArgs$1.invoke(FragmentNavArgsLazy.kt:42)
        at com.example.app.framework.ui.view.fragments.home.refactor.NewBaseEmailFragment$$special$$inlined$navArgs$1.invoke(Unknown Source:0)
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:44)
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34)
        at com.example.app.framework.ui.view.fragments.home.refactor.NewBaseEmailFragment.getToolbarTitleArgs(Unknown Source:4)
        at com.example.app.framework.ui.view.fragments.home.refactor.NewBaseEmailFragment.initToolbar(NewBaseEmailFragment.kt:59)
        at com.example.app.framework.ui.view.fragments.home.refactor.NewBaseEmailFragment.onViewCreated(NewBaseEmailFragment.kt:47)
        at com.example.app.framework.ui.view.fragments.home.calibrateAndRepair.CalibrateRepairOptionFragment.onViewCreated(CalibrateRepairOptionFragment.kt:23)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:332)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1199)
        at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2236)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2009)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1965)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1861)
        at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
1

There are 1 best solutions below

1
shaheer cs On

You can avoid the null arguments error by setting default argument and you need to check the argument before using it(whether it is expected value or default value)

Thank you