25

I found the question but does not have solution in code

I want to have data when backpress/manual back happens. I am using navigateUp() to go back. How can I pass data to previous fragment? navigateUp() does not have any facility to pass data to previous fragment. Even I did not find solution using Safe Args. It's passing data forward. I want to have in backward Frad B -> Frag A.

My code to go back to previous fragment

Navigation.findNavController(view).navigateUp()

enter image description here

My question is, How can i get data in previous fragment. I can navigate to Frag A from Frag B using

6
  • 1
    2nd solution is singleton java. companion object in kotlin Commented Mar 12, 2019 at 6:37
  • Did you find any solution? Commented Jun 4, 2019 at 2:19
  • 1
    I have used companion object Commented Jun 5, 2019 at 14:58
  • I hope Android team soon will provide simple and convenient solution for this simple action. Commented Mar 14, 2020 at 3:46
  • Hi! Could you please post your solution @BhaveshHirpara? Commented Feb 15, 2021 at 19:13

6 Answers 6

11

According to developer.android.com, you can use common for fragments where you want to share data ViewModel using their activity scope.

Here are steps:

  1. Create view model which will keep the data:
class SharedViewModel : ViewModel() {
    val dataToShare = MutableLiveData<String>()

    fun updateData(data: String) {
        dataToShare.value = data
    }
}
  1. Observe data changes in Fragment1:
class Fragment1 : Fragment() {

    private lateinit var viewModel: SharedViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)
        viewModel.dataToShare.observe(this, Observer<String> { dataFromFragment2 ->
            // do something with data
        })
    }
}
  1. Update data in Fragment2 and if you're handling navigation properly, now, you should be able to receive data changes on Fragment1:
class Fragment2 : Fragment() {

    private lateinit var viewModel: SharedViewModel

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)

        updateDataButton.setOnClickListener { v ->
            viewModel.updateData("New data for fragment1")
        }
    }
}

I hope answer helps.

Sign up to request clarification or add additional context in comments.

5 Comments

Sharing ViewModel between Fragment will add complexity to the source code.
@Natig if I use SharedViewModel then I will have 2 viewModels in a fragment ? in FragmentA, I will have FragmentAViewModel and SharedViewModel, and in FragmentB, I will have FragmentBViewModel and SharedViewModel ? so the the shared view model only to pass the data back to previous fragment ?
@Natig or I just need to make make one viewmodel (SharedViewModel) for my two fragments ? I am confused. sorry I am a beginner
Thats why they have given support for shared view model guys
If you don't want to have 2 viewmodels (or a shared one) then think about the problem for one minute and come to the realization the problem is not the number of viewModels, is that the data you want to store, outlives both, and so it should be stored in a third place (repository?) and each fragment (and its different view models) should use the same repository to fetch the data. That is the "correct" (for 2021) approach I would have thought if this sharing was important. Alternatively, you can use the fragment result listener if data fits in a bundle/intent.
10

Please use the OFFICIAL androidx's components. setFragmentResultListener() and setFragmentResult() methods:

implementation "androidx.fragment:fragment-ktx:1.3.5"

Cheers ;)

Comments

7

You can use NavigationResult library. Basically it's startActivityForResult but for Fragments in Navigation component.

3 Comments

this is way too invasive even for a simple project.
@Alberto That's why we need to use the official Android's approach - stackoverflow.com/a/67530295/1225669
I wasn't aware of that, I'll check it out!
1

To pop destinations when navigating from one destination to another, add an app:popUpTo attribute to the associated <action> element. To navigate from fargment2 to Fragment1 with arguments, specify in the navigation graph the action of the caller fragment and the arguments of the destination fragment :

<fragment
    android:id="@+id/fragment2"
    android:name="com.example.myapplication.Fragment2"
    android:label="fragment_2"
    tools:layout="@layout/fragment_2">

    <action
        android:id="@+id/action_2_to_1"
        app:destination="@id/fragment1"
        app:popUpTo="@+id/fragment1"/>
</fragment>
<fragment
    android:id="@+id/fragment1"
    android:name="com.example.myapplication.Fragment1"
    android:label="fragment_1"
    tools:layout="@layout/fragment_1">

        <argument
            android:name="someArgument"
            app:argType="string"
            app:nullable="false"
            android:defaultValue="Hello Word"/>
</fragment>

In your Fragment2 class, you call your action and pass your argument:

   val action = Fragment2Directions.action2To1("MY_STRING_ARGUMENT")
        findNavController().navigate(action)

Comments

-1

You should use static variables/companion objects, because it is better than shared viewmodel as it is not simple/nice architecture. As it it not straightforward, I think it is the best way.

To navigateUp From FragmentB to FragmentA

FragmentB:

isBackpressed = true
findNavController().navigateUp() 

FragmentA:

onViewCreated() {
    // todo
    if(isBackpressed) {
         isBackpressed = false
         // do whatever you want
    }
}

1 Comment

this is a very bad practice. Also static variables wont survive configuration changes.
-4

You can just call

findNavController().navigate(R.id.fragment1, args)

where args is your bundle. In fragment1, fetch the data from the arguments

4 Comments

is this creating new fragment or is it navigating up? I want to back
@BhaveshHirpara Please see my answer here: stackoverflow.com/a/60570030/1225669
navigateUp() and navigate do two differents actions, This is not a good answer
This will just instantiate the fragment1 again

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.