One way I know that is through activity.We can send data from fragment to activity and activity to fragment Is there any other way.
There are two methods I'd consider viable:
A.Communicate with your owning activity and forward messages to other fragments via that owning activity, details on that can be found int he official android documentation here:
http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
Quote:
In some cases, you might need a fragment to share events with the activity. A good way to do that is to define a callback interface inside the fragment and require that the host activity implement it. When the activity receives a callback through the interface, it can share the information with other fragments in the layout as necessary.
The Communication interface could look something like this:
public interface IActionListener{
//You can also add parameters to pass along etc
public void doSomething();
}
The fragment would look something like this:
public class MyFragment extends Fragment{
private WeakReference actionCallback;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
actionCallback = new WeakReference((IActionListener) activity);
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement IActionListener.");
}
}
}
I am using a WeakReference here but that's really up to you. You can now use actionCallback to communicate with the owning activity and call the methods defined in IActionListener.
The owning Activity would look like this:
public class MyActivity extends ActionBarActivity implements IActionListener {
public void doSomething(){ //Here you can forward information to other fragments }
}
B. Now as for the second method - you can have fragments directly communicate with each other using interfaces as well - this way you don't have to know the exact class of the fragment you are talking to, which ensures loose coupling.
The setup is as follows: You have two fragments (or more) and an activity (to start the second fragment). We have an interface that lets Fragment 2 send a response to Fragment 1 once it has completed it's task. For the sake of simplicity we just re-use the interface I defined in A.
Here is our Fragment 1 :
public class FragmentOne extends Fragment implements IActionListener {
public void doSomething() {//The response from Fragment 2 will be processed here}
}
Using the method described in A. Fragment 1 asks it's owning Activity to start Fragment 2. However, the Activity will pass along Fragment 1 as an argument to Fragment 2, so Fragment 2 can later indirectly access Fragment 1 and send the reply. Let's look at how the Activity preps Fragment 2:
public class MyActivity extends ActionBarActivity {
// The number is pretty random, we just need a request code to identify our request later
public final int REQUEST_CODE = 10;
//We use this to identify a fragment by tag
public final String FRAGMENT_TAG = "MyFragmentTag";
@Override
public void onStartFragmentTwo() {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
// The requesting fragment (you must have originally added Fragment 1 using
//this Tag !)
Fragment requester = manager.findFragmentByTag(FRAGMENT_TAG);
// Prepare the target fragment
Fragment target = new FragmentTwo();
//Here we set the Fragment 1 as the target fragment of Fragment 2's
//communication endeavors
target.getSelf().setTargetFragment(requester, REQUEST_CODE);
// Hide the requesting fragment, so we can go fullscreen on the target
transaction.hide(requester);
transaction.add(R.id.fragment_container, target.getSelf(), FRAGMENT_TAG);
transaction.addToBackStack(null);
transaction.commit();
}
}
Hint: I am using the Support-Framework, so if you develop solely for > Android 3.0 you can simply use FragmentActivity instead of ActionBarActivity.
Now FragmentTwo is being started, let's look at how FragmentTwo would communicate with FragmentOne:
public class FragmentTwo extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(savedInstanceState != null){
// Restore our target fragment that we previously saved in onSaveInstanceState
setTargetFragment(getActivity().getSupportFragmentManager().getFragment(savedInstanceState, TAG),
MyActivity.REQUEST_CODE);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Retain our callback fragment, the TAG is just a key by which we later access the fragment
getActivity().getSupportFragmentManager().putFragment(outState, TAG, getTargetFragment());
}
public void onSave(){
//This gets called, when the fragment has done all its work and is ready to send the reply to Fragment 1
IActionListener callback = (IActionListener) getTargetFragment();
callback.doSomething();
}
}
Now the implementation of doSomething() in Fragment 1 will be called.