I have set up my app using the Navigation architecture component. Navigating from one fragment to the next fragment works fine. However I am stuck trying to pass data in that navigation flow.
Following the structure of the Navigation codelab app, I am using the code below to navigate from one fragment to the another on a menu item click:
MainActivity.kt
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return NavigationUI.onNavDestinationSelected(item,
Navigation.findNavController(this, R.id.nav_host_fragment))
|| super.onOptionsItemSelected(item)
}
I tried passing the bundle here by amending the code as follows. Android Studio does not detect any errors but my app crashes when I try to perform that menu item click. Note, I am passing R.id.menu_edit
as an parameter in findNavController
because otherwise I get a 'No value passed for parameter 'viewId'' build error - but I think you would normally call this without passing anything.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item?.itemId) {
R.id.menu_song_edit -> {
val songBundle = Bundle()
songBundle.putString("titleArg", song_title.toString())
this.findNavController(R.id.menu_song_edit).navigate(R.id.goto_songedit, songBundle) // *** this is line 96 where it crashes per the log ***
return true
}
else -> return NavigationUI.onNavDestinationSelected(item,
Navigation.findNavController(this, R.id.nav_host_fragment))
|| super.onOptionsItemSelected(item)
}
}
Log from crash below. NavController was not found?
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.projects.arise.mytestapp, PID: 1162
java.lang.IllegalStateException: Activity com.projects.arise.mytestapp.MainActivity@58f00cb does not have a NavController set on 2131230836
at androidx.navigation.Navigation.findNavController(Navigation.java:60)
at androidx.navigation.ActivityKt.findNavController(Activity.kt:30)
at com.projects.arise.mytestapp.MainActivity.onOptionsItemSelected(MainActivity.kt:96)
at android.app.Activity.onMenuItemSelected(Activity.java:3204)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:407)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:63)
at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:203)
at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:780)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:171)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:973)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:963)
at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:624)
at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:150)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756) Disconnected from the target VM, address: 'localhost:8610', transport: 'socket'
Then I tried overriding onOptionsItemSelected
in the fragment that's passing the data instead but that did not seem to have any effect. I'm guessing that's because it is being intercepted already by the same method in MainActivity.kt above.
The code I had in the data sending fragment was as follows. Resource ID 'goto_detailsedit' refers to the ID of the action
in the navigation nav_graph.xml file.
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.menu_edit -> {
val songBundle = Bundle()
songBundle.putString("nameArg", first_name.text.toString())
this.findNavController().navigate(R.id.goto_songedit, songBundle)
return true
}
else -> return super.onOptionsItemSelected(item)
}
}
Can someone please help me with the rookie syntax error in the MainActivity.kt code above?
UPDATE 2 Jul 2018
Going through the documentation again I found that the syntax should be as follows - I need to reference a view:
view.findNavController().navigate(R.id.confirmationAction, bundle)
I have already set up the toolbar in onCreate
in the main activity by calling:
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
So I tried referencing the toolbar by replacing this
with toolbar
:
toolbar.findNavController().navigate(R.id.goto_songedit, songBundle)
Android Studio code editor is now happy with it but my app still crashes. The log states that the NavController isn't set up yet:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.projects.arise.mytestapp, PID: 2670
java.lang.IllegalStateException: View android.support.v7.widget.Toolbar{d03bbdd V.E...... ........ 0,0-1080,147 #7f0800e0 app:id/toolbar} does not have a NavController set
at androidx.navigation.Navigation.findNavController(Navigation.java:83)
at androidx.navigation.ViewKt.findNavController(View.kt:28)
at com.projects.arise.mytestapp.MainActivity.onOptionsItemSelected(MainActivity.kt:96)
...
Is there something I'm missing? Or could this be a bug with Navigation?