Nullable argument in displayFragment (AndExplore-0.6, p 273-6)

from the CommonsWare Community archives

At May 17, 2019, 10:38pm, redpsalm asked:

In AndExplore-0.6, in Launching the EditFragment for Adds, p. 273-276, in navgraph.xml, shouldn’t the displayFragment argument modelId be nullable as well as in editFragment? I was not getting the “compile error in onViewCreated() of EditFragment” indicated on p. 276 but running the app was resulting in a fatal Java error, which I fixed by changing the displayFragment argument to nullable. Is this correct?

<?xml version=”1.0” encoding=”utf-8”?>

<fragment android:id="@+id/rosterListFragment" android:name="com.commonsware.todo.RosterListFragment"
          android:label="@string/app_name">
    <action android:id="@+id/displayModel" app:destination="@id/displayFragment"/>
    <action android:id="@+id/createModel" app:destination="@id/editFragment">
        <argument android:defaultValue="@null" android:name="modelId"
                  app:argType="string" app:nullable="true"/>
    </action>
</fragment>
<fragment android:id="@+id/displayFragment" android:name="com.commonsware.todo.DisplayFragment"
          android:label="@string/app_name">
    <argument android:name="modelId" app:argType="string" **app:nullable="true"**/>
    <action android:id="@+id/editModel" app:destination="@id/editFragment"/>
</fragment>
<fragment android:id="@+id/editFragment" android:name="com.commonsware.todo.EditFragment"
          android:label="@string/app_name">
    <argument android:name="modelId" app:argType="string" app:nullable="true"/>
</fragment>

At May 17, 2019, 10:52pm, mmurphy replied:

I have not needed that attribute, and the project works for me. Can you try removing it, then if you get a crash again, post the stack trace here? That might give me some clues.

There is no valid scenario that I can think of in the app for passing a null value for modelId to DisplayFragment, as then we have nothing to display.


At May 18, 2019, 7:58am, redpsalm replied:

Pretty easy to reproduce in my environment (Android Studio 3.4 with settings very close to yours, emulator API 28, Google Play): the only change was to make modelId in displayFragment non nullable. Here is the exception (when I click on Add):

2019-05-18 09:38:40.404 19091-19091/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.commonsware.todo, PID: 19091
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:52)
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34)
        at com.commonsware.todo.EditFragment.getArgs(Unknown Source:27)
        at com.commonsware.todo.EditFragment.onViewCreated(EditFragment.kt:30)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1471)
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2646)
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2416)
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2372)
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
     **Caused by: java.lang.IllegalArgumentException: Argument "modelId" is marked as non-null but was passed a null value.**
**            at com.commonsware.todo.DisplayFragmentArgs$Companion.fromBundle(DisplayFragmentArgs.kt:24)**
        at com.commonsware.todo.DisplayFragmentArgs.fromBundle(Unknown Source:21)
        at java.lang.reflect.Method.invoke(Native Method) 
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:52) 
        at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34) 
        at com.commonsware.todo.EditFragment.getArgs(Unknown Source:27) 
        at com.commonsware.todo.EditFragment.onViewCreated(EditFragment.kt:30) 
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1471) 
        at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2646) 
        at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2416) 
        at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2372) 
        at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273) 
        at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733) 
        at android.os.Handler.handleCallback(Handler.java:873) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

At May 18, 2019, 10:27am, mmurphy replied:

Check your EditFragment implementation and confirm that you did not somehow import something from DisplayFragment. There is no reason for EditFragment to be referring to DisplayFragment as it is in the stack trace.


At May 18, 2019, 4:43pm, redpsalm replied:

My imports are exactly the same as in the book, namely:

import android.os.Bundle
import android.view.*
import android.view.inputmethod.InputMethodManager
import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.commonsware.todo.databinding.TodoEditBinding

At May 18, 2019, 5:18pm, mmurphy replied:

Are you sure that args in your EditFragment is declared as:

 private val args: EditFragmentArgs by navArgs()

I can reproduce your problem if I use DisplayFragmentArgs instead of EditFragmentArgs. See Step #11 of the “Editing an Item” tutorial (page 253) for where args is added to EditFragment.


At May 18, 2019, 5:28pm, redpsalm replied:

Bingo! You’re absolutely right. It fixes the problem… and it makes sense (now that I know what the issue is!). BTW after a couple of weeks, I really love your approach (books + online updates). I had tried online video training but with very limited success and too much time listening to lengthy videos.


At May 18, 2019, 5:40pm, mmurphy replied:

Ah, good. I was getting worried that there was some bug in the Navigation component that you were tripping over…

Thanks for the kind words! Tell your friends! :grin:

note to self: don’t create lengthy training videos…