Nullable argument in displayFragment (AndExplore-0.6, p 273-6)
from the CommonsWare Community archivesAt 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!
note to self: don’t create lengthy training videos…