Everytime i am in need of having a shared data to use or to be updated in fragment, i always put the data in activity and create a method to get/update the data then access it in fragment through something like this
(activity as HomeActivity).updateData()
i feel like this is not the good way to do this, is there any better way to do this? having the same object to be accessed through different fragment
I am a newbie so any advice will be really appreciated, Thanks
Please try the following:
Create a singleton class
In the singleton class create empty or valued variables
Create getter/setter for those variables if required
Access the variables from other classes/activities using the singleton object of the data holder class
This a system from MVP/MVC architecture and a very good practice
Whenever you replace fragment from Activity or from anywhere you can pass data to fragment by setting data as Arguments.
Testfragment = new TestFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("key",<data to pass>);
fragment.setArguments(bundle);
replaceFragment(fragment);
Access same data in fragment by using
Object obj = getArguments().getSerializable("key")
Related
What is the best way to access data members of an activity from its fragment
Some ways which I know include -
Create an interface in the Fragment which the Activity will implement. The interface will have the methods to access data members of the Activity.
Directly access using ((Activity)getActivity).getXXX() from the fragment.
Pass the data members or custom parcelable class to newInstance method of the fragment and set the fragment arguments as the class for e.g. -
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
and later we can get the arguments using getArguments()
Which method is the best and what are the drawbacks of each?
Actually the combination of the first and third method is the best. The second one should be avoided at all cost since this strongly couples the Fragment to a specific Activity. This will defeat one of the main advantages of Fragments namely being able to use it in different Activities (plug and play).
As for the first and third method.
- The first one is how you will usually communicate from the Fragment to your Activity.
- The third one is how you'll usually instantiate your Fragment while passing data to it from your Activity. When you already have an instance of your Fragment running you'll have to fall back on your first method.
I have specific fragments which will perform actions in a background thread (or will start activities for result) and I would like to set a callback (from the hosting activity), to get some data from the fragment after such actions, for instance:
FragmentManager fm = getFragmentManager();
TakePhotoFragment takePhotoFragment = (TakePhotoFragment) fm.findFragmentById(R.id.frTakePhoto);
takePhotoFragment.setListener(new TakePhotoFragment.OnNewBitmapListener() {
#Override
public void onNewBitmap(Bitmap bitmap) {
// do things in the activity
}
});
I have read that it is safer to feed arguments into the fragment using Bundles, but there are several cases which I would like to pass object references rather than simple String data using Bundles. Is there any problem in getting a reference using a FragmentManager and calling methods on it? If yes, which are the workarounds?
If your fragment is not yet created use bundle, otherwise use instance one.
It is safer to pass bundle becoz when android recreate your fragment your pass data in bundle is not lost.
If you use the instance one to pass data you have to save and restore that data yourself
Note: you can pass complex object through bundle by making them parcelable or serializable.
Also passing big data in bundle is not recommended
If your fragment is defined in xml you can get the instance by findFragmentById() of fragmentManager class
For some reason my understanding was that a headless Fragment lives for the duration of your application. With this understanding, in my attempt to persist an object between startActivityForResult() I put the object in a Headless Fragment like this
private HeadlessFragment modelFragment;
modelFragment = (HeadlessFragment)
getSupportFragmentManager().findFragmentByTag(Constants.HEADLESS_FRAGMENT_TAG);
if (modelFragment == null){
modelFragment = new HeadlessFragment();
}
modelFragment.setInvoice(invoice);
I can confirm that the custom object was set, however when I go to the next activity and try to get the same object by calling findFragmentByTag with same tag the object is null.
Does a Headless Fragment survive between two Activities life cycle? I did set setRetainInstance(true) on that Headless Fragment. I was hoping that I will not have to implement Parceable on my custom object.
For some reason my understanding was that a headless Fragment lives for the duration of your application.
No. Fragments are owned by activities and are not application-wide constructs.
I can confirm that the custom object was set, however when I go to the next activity and try to get the same object by calling findFragmentByTag with same tag the object is null.
There are at least two reasons for this:
First, at least in the code that you are showing, you never add the fragment to the FragmentManager via a FragmentTransaction. As such, the activity that created the fragment will not be able to find the fragment via findFragmentByTag(), because the FragmentManager does not know about it.
Second, each activity has its own FragmentManager, and fragments from one activity are not accessible in another activity.
I was hoping that I will not have to implement Parceable on my custom object.
Then don't pass the object. Pass the information (e.g., a key or ID) by which the other activity can retrieve the object (from a singleton POJO cache, by querying the database, etc.).
Or, do not make them separate activities, but have them as separate (regular) fragments in one activity.
Or, implement Serializable, though Parcelable executes more quickly.
I have a custom class called Data which contains all the data. The main activity creates two fragments. I have a field in the main activity like this:
private Data data = new Data();
The fragments are created with this method:
private ArrayList<Fragment> getFragments() {
ArrayList<Fragment> fragments = new ArrayList<Fragment>();
fragments.add(new fragment_one());
fragments.add(new fragment_two());
return fragments;
}
I need to pass the data field to the fragments, so the fragments can acces the methods of Data.
I tried by creating a bundle, but I can't pass a custom class. What can I do?
Bundles can accept custom classes, if they implement either Parcelable or Serializable, Parcelable is faster but more work to implement and Serializable is easier to implement, but slower.
Then you can do this:
Bundle bundle = new Bundle();
bundle.putSerializable("MyData", data);
fragment_one.setArguments(bundle);
Now fragment_one will have access to data in it's onCreate(Bundle bundleHoldingData) method.
Another option is to have a public setter in your fragment that takes in data. Benefit of this is you don't have to wait till data is ready to add the fragment.
Data needs to either implement Parcelable or Serializable.
You can then either use bundle.putParcelable() or bundle.putSerializable() to pass the data to both fragments via the setArguments() method.
You should not pass references to fragments, all your data should be passed using setArguments (unless your fragment is retained). The reason is that android might destroy your fragment during configuration change, and recreate it during activity creation.
So you should either pass your data inside setArguments, or give access to it using singleton class, ie. application class.
[edit] - havent tried this myself but you can find online tools to make your data class parcelable, here is one: http://devk.it/proj/parcelabler/
You can set a static object depending how much data you keep and careful with the memory leaks. That way you can reach it within the fragments. But making the data parcelable and pass it with the bundle is always a better choice.
One option is to provide an accessor for the data on the Activity class. Then, in your fragment, you call getActivity(), cast it to the derived type, and get the data, as needed.
This of course creates a dependency from your fragment to the activity, but if it's not meant to be a generic, re-usable fragment, it would be very simple and straightforward to implement and means you can get a reference to the current Activity data and not a copy like the Bundle / Parcelable / Serializable strategy would.
I have an object in my main activity that stores a bunch of data from an XML document and I want to be able to access that information on several different fragments to display the information. How can I go about doing that
Your object can implements java.ioSerializable . Than you are allowed to pit an instance of this object into the android bundle with putSerializable. Finally you can use the setArguments method to pass the bundle instance through your fragment