Passing data from fragment to fragment - android

I have two activities says Activity A and Activity B.
Activity A contains Fragments AF1,AF2.
Activity B contains Fragments BF1,BF2.
Currently I am in AF1.
How can we pass data(bundle) from AF1 to AF2?
How can we pass data (bundle) from AF1 to BF2?

The first approach is to use interfaces. Here is a breakdown of the steps:
Create an interface in your AF1 fragment - a method in that interface will be called and the data passed back through the arguments passed to it. In your activity, you implement that interface and override the method. Once the method is called, you could create another method in AF2 which you can easily call and pass the corresponding values.
The above described process has been shown in this tutorial: how to communicate between fragments and activities
FragmentOne.java
public class FragmentOne extends Fragment{
private Activity activity;
#Override
public void onAttach(Activity act){
super.onAttach(act);
activity = act;
}
#Override
public View onCreateView(..........){
/* somethind was clicked here*/
try{
((OnSomethingClickedListener) activity).updateActivity(position);
}catch(ClassCastException e){}
return view;
}
public interface OnSomethingCllickedListener{
void updateActivity(int position);
}
}
In your activity, implement the interface and override the method above:
public class ActivityOne extends Activity implements FragmentOne.OnSomethingCllickedListener{
#Override
public void onCreate(Bundle saveInstanceState){
/* as usual here */
}
#Override
public void updateActivity(int position){
/* call FragmentTwo's method here to update the view based on the position of item clicked here*/
FragmentTwo.updateView(position);
}
}
Secondly, to decouple your activities from your fragments, use EventBus library. This is quite simple and goes like this:
Download the jar file and add it to your project.
Create an Event class
Register for Events in your activities (unregister inside onDestroy)
When you want to notify the activity of the events, just call EventBus' post method and pass back the respective data.
Inside your activity, you need a method onEvent(YourEventClassName event) then you can pass the values respectively to your fragments as needed.
I hope this helps.

Code to pass and retrieve data:
Bundle bundle =new Bundle();
bundle.putString("message", message);
Frag1 _fragment = new Frag1();
fragmentTransaction.replace(android.R.id.content, _fragment);
fragmentTransaction.commit();
Bundle bundle=getArguments(); //get data
if(bundle!=null)
{
message=bundle.getString("message") ;
}

Related

transfer data from fragment A -> fragment B - > fragment C. When user click Back button, I want to return to fragment A and data

I'm a newbie in android developer. I have a question about transfer with 3 fragments.
I have 3 fragments (A - B - C). I want o transfer data from A -> B -> C.
In each the fragment, data was been changed.
When user click BACK BUTTON, user want to return A with the updated data.
How to return fragment A with the update data?
Thanks.
Here is a sample idea how to achieve communication.
// activity classs
public class SampleActivity extends Activity implements OnFragmentChangeListener {
OnBackPressListener dataFragment;
public void onCreate(bundle){
android.app.FragmentManager fragmentManager=getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
dataFragment = new DataFragment();
fragmentTransaction.add(R.id.audio_permission_button,dataFragment);
fragmentTransaction.commit()
}
#override
public void OnFragmentChange(Bundle bundle){
//here you go.
// write code to load new fragment with same idea. now you have bundle do what you want.
}
#Override
public void onBackPressed() {
// you can call this method from any click event, This just an sample idea.
dataFragment.OnActivityBackPress();
}
}
// interface to communicate with fragment
public interface OnFragmentChangeListener {
public void OnFragmentChange()
}
// fragment class
public class DataFragment extends Fragment implements OnBackPressListener {
OnFragmentChangeListener onFragmentChangeListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onFragmentChangeListener=(OnFragmentChangeListener) getActivity();
}
#Override
public void OnActivityBackPress() {
// pass you data to activity for loading new fragment or to refresh data.
Bundle bundle= new Bundle();
onFragmentChangeListener.OnFragmentChange(bundle);
}
}
// interface behave like mediator
public interface OnBackPressListener {
public void OnActivtiyBackPress();
}
Use interface to achieve this. Implements interface in fragment and activity, as it's a good way to communicate between fragment through activity. Then send the data through interface and extract the data from it.
You can use Interface class to communicate between fragment but it must make sure all the fragment is alive.
You can use SharedPreferences where you can save the data and retrieve it anywhere you like

how to pass data from a java class to a fragment in android

So i have a FragmentPagerAdapater called SectionsPagerAdapter and a fragment called TeamFragment where I display data from a specific team. So basically I don't want to create different fragments for each team. That is an overkill. I just want 1 fragment which basically connects to the backend then collects the data based on the team then displays that data. But I dont know how to pass the Team name(a string type) from SectionsPagerAdapter to the TeamFragment so that in TeamFragment, I can easily know what to retrieve from the backend. My backend in parse.com. Please help me figure this out and learn. Thanks
So this is was solved my problem. In my sectionsPagerAdapter class i had the below code
Bundle args = new Bundle();
args.putString("TeamName", team);
TeamFragment teamFragment = new TeamFragment();
teamFragment.setArguments(args);
In onCreateView of my TeamFragment, i had the following
Bundle bundle = this.getArguments();
mTeam = bundle.getString("TeamName");
hope this can help someone else. Thanks
Communicating data into fragments is typically done through a simple setter function that is called by the activity that instantiates or contains the fragment:
public class MyActivity extends FragmentActivity {
#Override
protected void onCreate(Bundled savedInstanceState) {
// ...
TeamFragment fragment =
(TeamFragment) (getSupportFragmentManager().findFragmentById(fragmentId));
fragment.setTeamName(teamName);
// ...
}
For communicating data back to the activity, is typically done using a fragment-specific "Listener" interface. This listener can be attached using the same method (by calling a method on the fragment in the parent activity to register the listener) or it can be done by requiring that the parent Activity implement the listener interface, and casting the parent activity to this listener interface in onAttach() (though the latter approach is not as clean of an approach). Example:
public class MyActivity extends FragmentActivity {
#Override
protected void onCreate(Bundled savedInstanceState) {
// ...
TeamFragment fragment =
(TeamFragment) (getSupportFragmentManager().findFragmentById(fragmentId));
fragment.setTeamName(teamName);
fragment.setTeamSelectedListener(new TeamSelectedListenerImpl());
// ...
}
Or:
public class TeamFragment extends Fragment {
public interface TeamSelectedListener {
// ...
}
// ...
#Override
protected void onAttach(Activity activity) {
teamSelectedListener = (TeamSelectedListener) activity;
}
// ...
}
public class MyActivity
extends FragmentActivity
implements TeamFragment.TeamSelectedListener {
// ...
}

Pass data from A and B fragments to C fragements

I have created three fragments A, B and C. In fragment A I'm having First Name and Last Name. In fragment B I'm having Age, City, Area and Address. In C I'm having Profession and Experience. In frag C I'm also having a button which sends all the info to the server. Now how can I have the info from fragment A and B in fragment C. I have used Bundle to send the info but it's a tedious task. Any simple method available?
E.g.:
Bundle args = new Bundle ();
args.putString ("first_name", strFirstName);
args.putString ("last_name", strLastName);
Instead of passing data from fragment A and B to C, pass them to the Activity via callback, and then pass the "send to server" action callback so that the Activity handles it:
class Fragment A {
// fragment definition
public interface OnUserInformationTypedListener {
public void onUserInformationTyped(String name, String lastName);
}
}
class FragmentB {
// fragment definition
public interface OnUserExtraInformationTypedListener {
public void onUserExtraInformationTyped(int age, String address);
}
}
class FragmentC {
// fragment definition
public interface OnUserCareerInformationTypedListener {
public void onUserCareerTyped(String profession, String experience);
public void onSendToServer();
}
}
Then make the Activity implements all interfaces:
class MyActivity extends Activity implements OnUserInformationTypedListener,
OnUserExtraInformationTypedListener, OnUserCareerInformationTypedListener {
#Override
public void onUserInformationTypedListener(String name, String lastName) {
// Probably pass local variable to private attributes
}
// Override the rest of the interface's methods
#Override
public void onSendToServer() {
// Send information to the server logic
}
}
And finally, make the FragmentA, FragmentB and FragmentC each one an instance of their respective callback, i.e:
// Inside FragmentA
private OnUserInformationTypedListener listener = null;
And then you pass the listener reference to it, Either by calling Fragment#onAttach(Activity) or via public method:
// Inside FragmentA
#Override
public void onAttach(Activity activity) {
listener = (OnUserInformationTypedListener) activity;
}
// if you prefer public setter then create the setter and call it from the Activity:
// Inside Activity#onCreate or wherever you instantiate the fragment
FragmentA fa = new FragmentA();
fa.setOnUserInformationTypedListener(this);
For more information on how to communicate Fragments via the host Activity (this is the right way to do it), read this http://developer.android.com/training/basics/fragments/communicating.html
The Fragment documentation says:
Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
So, its not a good idea to pass message from one fragment to another. Check the basics fragment training docs
Any simple method available?
You can save the data in a common class, and access the same from the other fragments..
use this i want to pass data on button click like this
btn_camera.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
}
});
and get data oncreate method of fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}

Send data from activity to fragment in Android

I have two classes. First is activity, second is a fragment where I have some EditText. In activity I have a subclass with async-task and in method doInBackground I get some result, which I save to variable. How can I send this variable from subclass "my activity" to this fragment?
From Activity you send data with intent as:
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
and in Fragment onCreateView method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false);
}
Also You can access activity data from fragment:
Activity:
public class MyActivity extends Activity {
private String myString = "hello";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
...
}
public String getMyData() {
return myString;
}
}
Fragment:
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
MyActivity activity = (MyActivity) getActivity();
String myDataFromActivity = activity.getMyData();
return view;
}
}
I´ve found a lot of answers here # stackoverflow.com but definitely this is the correct answer of:
"Sending data from activity to fragment in android".
Activity:
Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();
Fragment:
Reading the value in the fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = this.getArguments();
String myValue = bundle.getString("message");
...
...
...
}
or just
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String myValue = this.getArguments().getString("message");
...
...
...
}
This answer may be too late. but it will be useful for future readers.
I have some criteria. I have coded for pick the file from intent. and selected file to be passed to particular fragment for further process. i have many fragments having the functionality of File picking. at the time , every time checking the condition and get the fragment and pass the value is quite disgusting. so , i have decided to pass the value using interface.
Step 1: Create the interface on Main Activity.
public interface SelectedBundle {
void onBundleSelect(Bundle bundle);
}
Step 2: Create the SelectedBundle reference on the Same Activity
SelectedBundle selectedBundle;
Step 3: create the Method in the Same Activity
public void setOnBundleSelected(SelectedBundle selectedBundle) {
this.selectedBundle = selectedBundle;
}
Step 4: Need to initialise the SelectedBundle reference which are all fragment need filepicker functionality.You place this code on your fragment onCreateView(..) method
((MainActivity)getActivity()).setOnBundleSelected(new MainActivity.SelectedBundle() {
#Override
public void onBundleSelect(Bundle bundle) {
updateList(bundle);
}
});
Step 5: My case, i need to pass the image Uri from HomeActivity to fragment. So, i used this functionality on onActivityResult method.
onActivityResult from the MainActivity, pass the values to the fragments using interface.
Note: Your case may be different. you can call it from any where from your HomeActivity.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
selectedBundle.onBundleSelect(bundle);
}
Thats all. Implement every fragment you needed on the FragmentClass. You are great. you have done. WOW...
The best and convenient approach is calling fragment instance and send data at that time.
every fragment by default have instance method
For example :
if your fragment name is MyFragment
so you will call your fragment from activity like this :
getSupportFragmentManager().beginTransaction().add(R.id.container, MyFragment.newInstance("data1","data2"),"MyFragment").commit();
*R.id.container is a id of my FrameLayout
so in MyFragment.newInstance("data1","data2") you can send data to fragment and in your fragment you get this data in MyFragment newInstance(String param1, String param2)
public static MyFragment newInstance(String param1, String param2) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
and then in onCreate method of fragment you'll get the data:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
so now mParam1 have data1 and mParam2 have data2
now you can use this mParam1 and mParam2 in your fragment.
Basic Idea of using Fragments (F) is to create reusable self sustaining UI components in android applications. These Fragments are contained in activities and there are common(best) way of creating communication path ways from A -> F and F-A, It is a must to Communicate between F-F through a Activity because then only the Fragments become decoupled and self sustaining.
So passing data from A -> F is going to be the same as explained by ρяσѕρєя K. In addition to that answer, After creation of the Fragments inside an Activity, we can also pass data to the fragments calling methods in Fragments.
For example:
ArticleFragment articleFrag = (ArticleFragment)
getSupportFragmentManager().findFragmentById(R.id.article_fragment);
articleFrag.updateArticleView(position);
I would like to add for the beginners that the difference between the 2 most upvoted answers here is given by the different use of a fragment.
If you use the fragment within the java class where you have the data you want to pass, you can apply the first answer to pass data:
Bundle bundle = new Bundle();
bundle.putString("edttext", "From Activity");
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
If however you use for example the default code given by Android Studio for tabbed fragments, this code will not work.
It will not work even if you replace the default PlaceholderFragment with your FragmentClasses, and even if you correct the FragmentPagerAdapter to the new situation adding a switch for getItem() and another switch for getPageTitle() (as shown here)
Warning: the clip mentioned above has code errors, which I explain later here, but is useful to see how you go from default code to editable code for tabbed fragments)! The rest of my answer makes much more sense if you consider the java classes and xml files from that clip (representative for a first use of tabbed fragments by a beginner scenario).
The main reason the most upvoted answer from this page will not work is that in that default code for tabbed fragments, the fragments are used in another java class: FragmentPagerAdapter!
So, in order to send the data, you are tempted to create a bundle in the MotherActivity and pass it in the FragmentPagerAdapter, using answer no.2.
Only that is wrong again. (Probably you could do it like that, but it is just a complication which is not really needed).
The correct/easier way to do it, I think, is to pass the data directly to the fragment in question, using answer no.2.
Yes, there will be tight coupling between the Activity and the Fragment, BUT, for tabbed fragments, that is kind of expected. I would even advice you to create the tabbed fragments inside the MotherActivity java class (as subclasses, as they will never be used outside the MotherActivity) - it is easy, just add inside the MotherActivity java class as many Fragments as you need like this:
public static class Tab1 extends Fragment {
public Tab1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
return rootView;
}
}.
So, to pass data from the MotherActivity to such a Fragment you will need to create private Strings/Bundles above the onCreate of your Mother activity - which you can fill with the data you want to pass to the fragments, and pass them on via a method created after the onCreate (here called getMyData()).
public class MotherActivity extends Activity {
private String out;
private Bundle results;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mother_activity);
// for example get a value from the previous activity
Intent intent = getIntent();
out = intent.getExtras().getString("Key");
}
public Bundle getMyData() {
Bundle hm = new Bundle();
hm.putString("val1",out);
return hm;
}
}
And then in the fragment class, you use getMyData:
public static class Tab1 extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
public Tab1() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.your_layout_name_for_fragment_1, container, false);
TextView output = (TextView)rootView.findViewById(R.id.your_id_for_a_text_view_within_the_layout);
MotherActivity activity = (MotherActivity)getActivity();
Bundle results = activity.getMyData();
String value1 = results.getString("val1");
output.setText(value1);
return rootView;
}
}
If you have database queries I advice you to do them in the MotherActivity (and pass their results as Strings/Integers attached to keys inside a bundle as shown above), as inside the tabbed fragments, your syntax will become more complex (this becomes getActivity() for example, and getIntent becomes getActivity().getIntent), but you have also the option to do as you wish.
My advice for beginners is to focus on small steps. First, get your intent to open a very simple tabbed activity, without passing ANY data. Does it work? Does it open the tabs you expect? If not, why?
Start from that, and by applying solutions such as those presented in this clip, see what is missing. For that particular clip, the mainactivity.xml is never shown. That will surely confuse you. But if you pay attention, you will see that for example the context (tools:context) is wrong in the xml fragment files. Each fragment XML needs to point to the correct fragment class (or subclass using the separator $).
You will also see that in the main activity java class you need to add tabLayout.setupWithViewPager(mViewPager) - right after the line TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); without this line, your view is actually not linked to the XML files of the fragments, but it shows ONLY the xml file of the main activity.
In addition to the line in the main activity java class, in the main activity XML file you need to change the tabs to fit your situation (e.g. add or remove TabItems). If you do not have tabs in the main activity XML, then possibly you did not choose the correct activity type when you created it in the first place (new activity - tabbed activity).
Please note that in the last 3 paragraphs I talk about the video! So when I say main activity XML, it is the main activity XML in the video, which in your situation is the MotherActivity XML file.
If you pass a reference to the (concrete subclass of) fragment into the async task, you can then access the fragment directly.
Some ways of passing the fragment reference into the async task:
If your async task is a fully fledged class (class FooTask extends AsyncTask), then pass your fragment into the constructor.
If your async task is an inner class, just declare a final Fragment variable in the scope the async task is defined, or as a field of the outer class. You'll be able to access that from the inner class.
From Activity you send data with Bundle as:
Bundle bundle = new Bundle();
bundle.putString("data", "Data you want to send");
// Your fragment
MyFragment obj = new MyFragment();
obj.setArguments(bundle);
And in Fragment onCreateView method get the data:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
String data = getArguments().getString("data");// data which sent from activity
return inflater.inflate(R.layout.myfragment, container, false);
}
Sometimes you can receive Intent in your activity and you need to pass the info to your working fragment.
Given answers are OK if you need to start the fragment but if it's still working, setArguments() is not very useful.
Another problem occurs if the passed information will cause to interact with your UI. In that case you cannot call something like myfragment.passData() because android will quickly tells that only the thread which created the view can interact with.
So my proposal is to use a receiver. That way, you can send data from anywhere, including the activity, but the job will be done within the fragment's context.
In you fragment's onCreate():
protected DataReceiver dataReceiver;
public static final String REC_DATA = "REC_DATA";
#Override
public void onCreate(Bundle savedInstanceState) {
data Receiver = new DataReceiver();
intentFilter = new IntentFilter(REC_DATA);
getActivity().registerReceiver(dataReceiver, intentFilter);
}
private class DataReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int data= intent.getIntExtra("data", -1);
// Do anything including interact with your UI
}
}
In you activity:
// somewhere
Intent retIntent = new Intent(RE_DATA);
retIntent.putExtra("data", myData);
sendBroadcast(retIntent);
Very old post, still I dare to add a little explanation that would had been helpful for me.
Technically you can directly set members of any type in a fragment from activity.
So why Bundle?
The reason is very simple - Bundle provides uniform way to handle:-- creating/opening fragment
-- reconfiguration (screen rotation) - just add initial/updated bundle to outState in onSaveInstanceState()
-- app restoration after being garbage collected in background (as with reconfiguration).
You can (if you like experiments) create a workaround in simple situations but Bundle-approach just doesn't see difference between one fragment and one thousand on a backstack - it stays simple and straightforward. That's why the answer by #Elenasys is the most elegant and universal solution. And that's why the answer given by #Martin has pitfalls
If an activity needs to make a fragment perform an action after initialization, the easiest way is by having the activity invoke a method on the fragment instance. In the fragment, add a method:
public class DemoFragment extends Fragment {
public void doSomething(String param) {
// do something in fragment
}
}
and then in the activity, get access to the fragment using the fragment manager and call the method:
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DemoFragment fragmentDemo = (DemoFragment)
getSupportFragmentManager().findFragmentById(R.id.fragmentDemo);
fragmentDemo.doSomething("some param");
}
}
and then the activity can communicate directly with the fragment by invoking this method.
the better approach for sending data from activity class to fragment is passing via setter methods. Like
FragmentClass fragmentClass = new FragmentClass();
fragmentClass.setMyList(mylist);
fragmentClass.setMyString(myString);
fragmentClass.setMyMap(myMap);
and get these data from the class easily.
Use following interface to communicate between activity and fragment
public interface BundleListener {
void update(Bundle bundle);
Bundle getBundle();
}
Or use following this generic listener for two way communication using interface
/**
* Created by Qamar4P on 10/11/2017.
*/
public interface GenericConnector<T,E> {
T getData();
void updateData(E data);
void connect(GenericConnector<T,E> connector);
}
fragment show method
public static void show(AppCompatActivity activity) {
CustomValueDialogFragment dialog = new CustomValueDialogFragment();
dialog.connector = (GenericConnector) activity;
dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
}
you can cast your context to GenericConnector in onAttach(Context) too
in your activity
CustomValueDialogFragment.show(this);
in your fragment
...
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
connector.connect(new GenericConnector() {
#Override
public Object getData() {
return null;
}
#Override
public void updateData(Object data) {
}
#Override
public void connect(GenericConnector connector) {
}
});
}
...
public static void show(AppCompatActivity activity, GenericConnector connector) {
CustomValueDialogFragment dialog = new CustomValueDialogFragment();
dialog.connector = connector;
dialog.show(activity.getSupportFragmentManager(),"CustomValueDialogFragment");
}
Note: Never use it like "".toString().toString().toString(); way.
just stumbled across this question, while most of the methods above will work.
I just want to add that you can use the Event Bus Library, especially in scenarios where the component (Activity or Fragment) has not been created, its good for all sizes of android projects and many use cases. I have personally used it in several projects i have on playstore.
You can create public static method in fragment where you will get static reference of that fragment and then pass data to that function and set that data to argument in same method and get data via getArgument on oncreate method of fragment, and set that data to local variables.
I ran into a similar issue while using the latest Navigation architecture component. Tried out all the above-mentioned code with passing a bundle from my calling activity to Fragment.
The best solution, following the latest development trends in Android, is by using View Model (part of Android Jetpack).
Create and Initialize a ViewModel class in the parent Activity, Please note that this ViewModel has to be shared between the activity and fragment.
Now, Inside the onViewCreated() of the fragment, Initialize the Same ViewModel and setup Observers to listen to the ViewModel fields.
Here is a helpful, in-depth tutorial if you need.
https://medium.com/mindorks/how-to-communicate-between-fragments-and-activity-using-viewmodel-ca733233a51c
Kotlin version:
In Activity:
val bundle = Bundle()
bundle.putBoolean("YourKey1", true)
bundle.putString("YourKey2", "YourString")
val fragment = YourFragment()
fragment.arguments = bundle
val fragmentTransaction = parentFragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.your_container, fragment, fragment.toString())
fragmentTransaction.commit()
In the Fragment onCreate():
var value1 = arguments?.getBoolean("YourKey1", default true/false)
var value2 = arguments?.getString("YourKey2", "Default String")
Smartest tried and tested way of passing data between fragments and activity is to create a variables,example:
class StorageUtil {
public static ArrayList<Employee> employees;
}
Then to pass data from fragment to activity, we do so in the onActivityCreated method:
//a field created in the sending fragment
ArrayList<Employee> employees;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
employees=new ArrayList();
//java 7 and above syntax for arraylist else use employees=new ArrayList<Employee>() for java 6 and below
//Adding first employee
Employee employee=new Employee("1","Andrew","Sam","1984-04-10","Male","Ghanaian");
employees.add(employee);
//Adding second employee
Employee employee=new Employee("1","Akuah","Morrison","1984-02-04","Female","Ghanaian");
employees.add(employee);
StorageUtil.employees=employees;
}
Now you can get the value of StorageUtil.employees from everywhere.
Goodluck!
My solution is to write a static method inside the fragment:
public TheFragment setData(TheData data) {
TheFragment tf = new TheFragment();
tf.data = data;
return tf;
}
This way I am sure that all the data I need is inside the Fragment before any other possible operation which could need to work with it.
Also it looks cleaner in my opinion.
You can make a setter method in the fragment. Then in the Activity, when you reference to the fragment, you call the setter method and pass it the data from you Activity
In your activity declare static variable
public static HashMap<String,ContactsModal> contactItems=new HashMap<String, ContactsModal>();
Then in your fragment do like follow
ActivityName.contactItems.put(Number,contactsModal);

How to pass result from second fragment to first fragment

In my app I have two fragments say fragmentA and FragmentB. When I click on a button in fragmetA, a list is opened in fragmentB. Now when I select an item from list in fragmentB I want the result to be passed to fragmentA. I am using only one TabActivity for all fragments. When list item is selected in fragmentB I am popping out fragmentB from stack so that I can directly go back to fragmentA.
Does anyone knows how to pass result to previous fragment.
Thanks.
Update
Activity is the parent controller and should take responsibility for handling those events raised by its fragments/views, which concern something outside of the scope of fragment/view itself.
A Fragment is to act as a sub-controller of Views it hosts. All the events and communication between its own views, the fragment should handle itself. When there is an event outside of a fragment's scope and responsibilities (like sending data to another fragment), that event should be escalated to its parent controller, the Activity.
Old
From this tutorial : http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
Its better to let the activity apply changes to its fragment than passing values directly between fragments. Let your Activity implement a FragmentListener interface with onQuery(Bundle data) and onResult(Bundle data) methods.
Create a FragmentListener varaible in each of your fragments and then override onAttach() of each fragment as:
public void onAttach(Activity activity) {
super.onAttach(activity);
//---register parent activity for events---
try{
fragmentListener = (FragmentListener) activity;
}catch (ClassCastException e)
{
throw new ClassCastException("Parent activity must implement interface FragmentListener.");
}
}
This will enforce your child fragments to be automatically registered to parent Activity.
Also, remember to release fragmentListener reference in onDetach().
Now you can call your Activity from fragments.
On the other side, your Activity can always search for a fragment using getFragmentManager().findFragmentByTag("fragmentA") or findFragmentById("FragmentA").
If it can find your Fragment, Then it can cast it into your FragmentA class and call its methods. Same can be done with FragmentB or any other fragment..
One of the possible solutions:
public class DetachableResultReceiver extends ResultReceiver {
private Receiver mReceiver;
public DetachableResultReceiver(Handler handler) {
super(handler);
}
public void clearReceiver() {
mReceiver = null;
}
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
public interface Receiver {
public void onReceiveResult(int resultCode, Bundle resultData);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
if (mReceiver != null) {
mReceiver.onReceiveResult(resultCode, resultData);
}
}
}
First fragment implements DetachableResultReceiver.Receiver and creates DetachableResultReceiver object:
mReceiver = new DetachableResultReceiver(new Handler());
mReceiver.setReceiver(this);
Then you can pass it to second fragment arguments:
Bundle bundle = new Bundle();
bundle.putParcelable(Consts.EXTRA_RECEIVER, receiver);
fragment.setArguments(bundle);
And use it in second fragment:
receiver = getArguments().getParcelable(Consts.EXTRA_RECEIVER);
receiver.send(Consts.SOME_MESSAGE, someData);
In fragmentB.java set an OnClickListener to perform a method in the main class. Pass an arguement in fragmentB.java to the main class that is the variable, and handle the rest of it in your main class. Though fragments shouldn't really be dependent on activities at all. Fragments were made to plug and play anywhere.
This Example Shows EditTextListener:
myAwesomeActivity.java
fragmentA.java
fragmentB.java
fragmentB.java:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
int x = 3;
EditText ed1 = (EditText) getView().findViewById(R.id.editText1);
ed1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()) {
((myAwesomeActivity) getActivity()).myMethod(x);
}
return false;
}
});
}
myAwesomeActivity.java:
publiv void myMethod (int x){
//Do whatever you want with variable
}
All you have to do is implement the correct type of listener, but the main point is shown. In one fragment activity, call a method and pass a variable to the main activity. From the main activity you can send it to your other fragment activity if you'd like.
You can also use SharedPreferences to save some string and after return back to the first fragment load it and clear.

Categories

Resources