androidkotlinnavigationmaterial-designnavgraph

Send call back to previous fragment with data using navigation graph


I am using navigation graph for the first time so need help regarding the same.

In my application I have MainActivity with 5 nested graphs.

<?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" android:id="@+id/main_navigation" app:startDestination="@+id/home_navigation"> <include app:graph="@navigation/home_navigation" /> <include app:graph="@navigation/explorer_navigation" /> <include app:graph="@navigation/favourite_navigation" /> <include app:graph="@navigation/server_navigation" /> <include app:graph="@navigation/settings_navigation" /> </navigation>

Now, I need suggestion for below things

1.Need to implement a common error screen for multiple error types with an action button.

2.Need to provide call back from this error screen on pressing action button with some data on previous screen

3.I also want to send action from child navigation to parent navigation to navigate on other destination.

Thankyou in advance.

For 1st, Currently I have added error fragment for separately for each nested graph which added overhead to handle error page separately.

`

<action android:id="@+id/action_global_fragment_settings"
    app:destination="@id/fragment_settings"/>

<fragment
    android:id="@+id/fragment_settings"
    android:name="com.xyz.android.ui.settings.SettingsBaseFragment"
    android:label="@string/title_settings">
    <action
        android:id="@+id/action_fragment_settings_to_fragment_error"
        app:destination="@id/fragment_error" />
    <action
        android:id="@+id/action_fragment_settings_to_settings_details_fragment"
        app:destination="@id/fragment_settings_details" />
</fragment>
<fragment
    android:id="@+id/fragment_error"
    android:name="com.xyz.android.ui.nodata.ErrorBaseFragment">
    <argument
        android:name="title"
        android:defaultValue="NO_DATA"
        app:argType="string" />
    <argument
        android:name="errorType"
        app:argType="com.xyz.android.ui.nodata.EnumErrorType"
        android:defaultValue="NO_DATA" />
</fragment>

<fragment
    android:id="@+id/fragment_settings_details"
    android:name="com.xyz.android.ui.settings.SettingsBaseFragmentDetails">
    <argument
        android:name="settingsConfig"
        app:argType="com.xyz.android.ui.settings.beans.SettingsConfigHelper$SettingsConfig" />
</fragment>

`

For 2nd, Still I have not found way to send call back to previous fragment with data.

For 3rd, I have used shared view model but need better approach.


Solution

  • There are a couple of techniques I use to manage navigation, while keeping code fairly simple:

    ERROR SCREENS

    I find separation of error summary and detail useful. My demo app renders an error summary fragment in the containing fragment, to avoid the need for navigation just to present an error. In my demo app this renders a red link:

    error summary

    When the red text is clicked, an error details fragment is displayed as a modal dialog, which again avoids navigation, and makes it easy to return a result to the current fragment:

    error details

    NAVIGATION FROM A FRAGMENT

    A fragment can ask the navigation system to update the current location, as in this example code:

    val args = Bundle()
    args.putString(Constants.ARG_COMPANY_ID, viewModelItem.company.id.toString())
    findNavController().navigate(R.id.transactions_fragment, args)
    

    EVENTS

    When navigation gets complex, a publish subscribe model of communication is often useful. For example, I like this EventBus project. Any view can register for events like this:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        EventBus.getDefault().register(this)
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        EventBus.getDefault().unregister(this)
    }
    
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMessageEvent(event: ReloadDataEvent) {
        this.reloadData(event.someData)
    }
    

    Then any other view can raise the event, when something happens that means other views should be informed, eg to reload their data. The code needed is pretty simple also.

    EventBus.getDefault().post(ReloadDataEvent(someData))
    

    DEMO APP

    If any of this is useful you can run my demo app and adapt its code to your own preferences.