Passing data back to previous fragment from current fragment
Asked Answered
L

3

26

I am Using Navigation Drawer in my app. I have one MainActivity and rest of are Fragments. So the issue is Suppose i have three fragments like A,B,C.

Now in A i have one button and i am sending data from A>B.
For example putSring("datafrom A","datafrom A");
Now in B i receive data From A.
I have one button in B,and i am sending data from B>C.
For example putSring("datafrom B","datafrom B");
Now in C i receive data From B.
Then, I have one Button in C,and sending data from C>B.
For example putSring("datafrom C","datafrom C");

So,seems like in B i am getting data from two different fragments. I tried with all using activity and it work well with startActivityforresult. but how can i manager when all are fragments.

Lamination answered 10/3, 2017 at 6:16 Comment(7)
While u are sending data from A->B , than u have to manitain the BOOLEAN that i am from A and same case C->A , u have to use the same BOOLEAN that specify that u are from c and sending data to BZigrang
but how will i check? from which fragment it is passedLamination
While u are send data from A->B use the BOOLEAN value TRUE.....And when u are sending data from C->A , use the BOOLEAN value FALSEZigrang
but when you pass data from A>B on that time app will crash with NPE. reasone will it wont get false of C>B ..got it?Lamination
If only one fragment is active at a time, seems like in B i am getting data from two different fragments is impossible. Furthermore, if you use setArguments() on Fragment objects, you dont have to worry about that.Soviet
@Lamination Check my below solution, and let me know in case of concernZigrang
If some is looking for an answer in 2021 for Navigation Component: Check out https://mcmap.net/q/535526/-pass-data-back-to-previous-fragment-using-android-navigationPawl
Z
5

When u are sending the data from Fragment A to Fragment B use the same boolean like below:-

FragmentA -> FragmentB

FragmentB ldf = new FragmentB ();
Bundle args = new Bundle();
args.putBoolean("BOOLEAN_VALUE",true);
ldf.setArguments(args);

getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();

And when u are send data from Fragment C to Fragment B use the same BOOLEAN which is used in Fragment A to B like below-

FragmentC -> FragmentB

FragmentB ldf = new FragmentB ();
    Bundle args = new Bundle();
    args.putBoolean("BOOLEAN_VALUE",false);
    ldf.setArguments(args);

    getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();

And in the last we have to check that value is recevied in FragmentB is from where like Fragment A OR FragemntC

FragmentB

   Boolean getValue= getArguments().getBoolean("BOOLEAN_VALUE");  
   if(getValue)
   {
    //VALUE RECEIVED FROM FRAGMENT A
   }
   else
   {
   //VALUE RECEIVED FROM FRAGMENT C
   }
Zigrang answered 10/3, 2017 at 6:35 Comment(5)
nice one..i am trying but make it putBooleanLamination
@Lamination ,Sorry i have updated the solution..plz check it..And let me know is it working for u or notZigrang
@Lamination ..Is it workable for u?? Than plz mark the answer right as it will help to others who become also stuck in the futureZigrang
but the value which i get from A will become null while i come from C>BLamination
What is the use of the values of A, while u are coming from C->B....U can do one more thing is that...u an send the valeue of A from B->C..And than u can revceive it baack from C->BZigrang
L
74

UPDATE

Starting with Androidx Activity 1.2.0-alpha02 and Androidx Fragment 1.3.0-alpha4, the official Android developer guide recommends to use the Activity/Fragment Result APIs over the deprecated Activity.onActivityResult(int, int, Intent) and Fragment.setTargetFragment(Fragment, int) methods:

it is strongly recommended to use the Activity Result APIs introduced in AndroidX Activity 1.2.0-alpha02 and Fragment 1.3.0-alpha02.

Thus, to pass data back to fragment B from C, call setFragmentResultListener() on fragment B's FragmentManager, as shown in the following example:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact
    setFragmentResultListener("requestKey") { requestKey, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported
        val result = bundle.getString("bundleKey")
        // Do something with the result
     }
}

In fragment C, set the result on the same FragmentManager by using the same requestKey using the setFragmentResult() API. Example:

setFragmentResult("requestKey", bundleOf("bundleKey" to "result"))

More details can be found at this guide.


The below answer is deprecated

You may call setTargetFragment() when you start the Fragment C from B. Example:

FragmentC fragmentC = FragmentC.newInstance();
fragmentC.setTargetFragment(FragmentB.this, REQUEST_CODE);
getFragmentManager().beginTransaction().replace(R.id.container, fragmentC).commit();

and then when you want to pass data back to fragment B from C, you can call the following code:

getTargetFragment().onActivityResult(
                getTargetRequestCode(),
                Activity.RESULT_OK,
                new Intent().putExtra("datafrom C", "datafrom C")
);

and get it from the onActivityResult() method in your fragment B:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode==REQUEST_CODE && resultCode==Activity.RESULT_OK) {
        String datafromC = data.getStringExtra("datafrom C");   
    }
}
Languid answered 10/3, 2017 at 6:28 Comment(5)
can not resolve newInstance() and can not resolve REQUEST_CODELamination
newInstance() is a method which I always use to init the fragment, you may call FragmentC fragmentC = new FragmentC(); instead.Languid
The REQUEST_CODE is a constant integer, which to let you to identify which fragment is triggered the onActivityResult() method, you may just assign an integer to it, if fragment C is the only fragment that passes data back to your fragment B. E.g. fragmentC.setTargetFragment(FragmentB.this, 1); and then check requestCode==1 in the fragment B's onActivityResult() method.Languid
Such a neat, simple and native way. Yet it seems that loads of people are unaware about itSwot
@KirillStarostin what exactly is neat about manually calling onActivityResult?Flaherty
Z
5

When u are sending the data from Fragment A to Fragment B use the same boolean like below:-

FragmentA -> FragmentB

FragmentB ldf = new FragmentB ();
Bundle args = new Bundle();
args.putBoolean("BOOLEAN_VALUE",true);
ldf.setArguments(args);

getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();

And when u are send data from Fragment C to Fragment B use the same BOOLEAN which is used in Fragment A to B like below-

FragmentC -> FragmentB

FragmentB ldf = new FragmentB ();
    Bundle args = new Bundle();
    args.putBoolean("BOOLEAN_VALUE",false);
    ldf.setArguments(args);

    getFragmentManager().beginTransaction().add(R.id.container, ldf).commit();

And in the last we have to check that value is recevied in FragmentB is from where like Fragment A OR FragemntC

FragmentB

   Boolean getValue= getArguments().getBoolean("BOOLEAN_VALUE");  
   if(getValue)
   {
    //VALUE RECEIVED FROM FRAGMENT A
   }
   else
   {
   //VALUE RECEIVED FROM FRAGMENT C
   }
Zigrang answered 10/3, 2017 at 6:35 Comment(5)
nice one..i am trying but make it putBooleanLamination
@Lamination ,Sorry i have updated the solution..plz check it..And let me know is it working for u or notZigrang
@Lamination ..Is it workable for u?? Than plz mark the answer right as it will help to others who become also stuck in the futureZigrang
but the value which i get from A will become null while i come from C>BLamination
What is the use of the values of A, while u are coming from C->B....U can do one more thing is that...u an send the valeue of A from B->C..And than u can revceive it baack from C->BZigrang
W
4

Things changed a lot since 2017. The answer I post is basically an example from https://developer.android.com and it presents a good solution where your fragments, in any number, do not know anything about each other and still you are able to create a simple and elegant mechanism that can be used without much struggle.

The answer is based on ViewModels and LiveData.

Note: If you are not familiar with Architecture Components I strongly advise you to learn about it as much as you can any time you can as it will increase your production speed and decrease the number of errors in your projects.

Everything below is a citation from the following link: source (Kotlin/Java)

Share data between fragments

It's very common that two or more fragments in an activity need to communicate with each other. Imagine a common case of master-detail fragments, where you have a fragment in which the user selects an item from a list and another fragment that displays the contents of the selected item. This case is never trivial as both fragments need to define some interface description, and the owner activity must bind the two together. In addition, both fragments must handle the scenario where the other fragment is not yet created or visible.

This common pain point can be addressed by using ViewModel objects. These fragments can share a ViewModel using their activity scope to handle this communication, as illustrated by the following sample code:

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
            // Update the UI
        })
    }
}

Notice that both fragments retrieve the activity that contains them. That way, when the fragments each get the ViewModelProvider, they receive the same SharedViewModel instance, which is scoped to this activity.

This approach offers the following benefits:

  • The activity does not need to do anything, or know anything about this communication.
  • Fragments don't need to know about each other besides the SharedViewModel contract. If one of the fragments disappears, the other one keeps working as usual.
  • Each fragment has its own lifecycle, and is not affected by the lifecycle of the other one. If one fragment replaces the other one, the UI continues to work without any problems.
Weldonwelfare answered 2/6, 2020 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.