I'm trying to do this without using a bundle. The reason I am trying to avoid that is because the data is pulled from a database online and I don't want the fragments to not load while it's waiting to get the data. From what I can tell I can only do the bundle arguments if the data is ready to send before any of the fragments are created.
This would cause a problem because the data isn't pulled from the database until the ViewPager is created. I can successfully pass the variables, but like I said the data isn't there instantaneously. This ends up sending a zero value through the bundle variable.
Am I incorrect in assuming you can't still pass bundles after the fragment creation? Aside from Bundles, what would be the best way to send a variable from the ViewPager to the Fragment? Would storing the data in the cache be a good option?
You can setup a method within your fragment to be called from your activity once you have retrieved said data from database. Then within your fragment method you can load it to where ever you need and however you need.
Only thing you have to be concerned about is the static context of the method.
You could cast your Activity to Fragment.getActivity then invoke a getter for your data.
Alternatively, you could use a Loader and implement LoaderManager.LoaderCallbacks in your Fragment to return the data from your database, but only initialize it once the data has been set.
I suppose you could also show some sort of loading Fragment, then replace it with the other after the data is set. You could use a Bundle in that case.
There are lots of ways to solve this. And yeah, the Fragments arguments can't be passed after creation, unless you call Fragment.setArguments before it's attached to the Activity.
Source
Fragment.instantiate
Fragment.setArguments
Related
I have one Activity and want to share data between that Activity and fragments. I put data in extra while in a fragment and put also other data in it. That way I Have a shared Bundle across my application. I only see examples of passing a Bundle to an Intent but its also possible to change that data while in another fragment. This does not break with the self-containment of fragments. I dont put them in some method in activity because then you will have to cast the activity. Can anybody tell me its right to do? I know about shared pref but I dont want a file based solution. I know about passing parameters with newInStance but I also need to save data back in fragments. passing parameters is only forward not shared.
Passing data from activity/fragment back & forth using Bundles would have some limitations and issues for instance:
To pass a complex object, you'd need to use a serializable marked with a key.
Keeping shared keys in different parts can lead to runtime
errors or data loss if keys are wrong.
Serialized objects are not recommended, but it can be solved with Parcelables. But maintaining that is not that easy for complex objects check here, and you would need to customize that for different types of objects.
Still you don't share data among different fragments but they're just transported; and need to be transported over and over again when you go to a new part of your app.
Not guaranteed to keep the data if the activity is recreated.
Instead of that you'd use ViewModels through MVVM structure where:
Data can be shared on different levels of lifecycle scopes; this means that if the ViewModel is instantiated through ViewModelProvider in activity; then it can be accessed in any part of the activity, or underlying fragments. And if you want to keep only data shared between any fragment and its underlying fragments; you'd bound the ViewModel instantiation to that fragment instead.
ViewModel is instantiated once in the owner, and accessed in the subordinate fragments with no re-instantiation.
If the activity is re-created, it receives the same ViewModel instance that was created by the owner, and the view's data won't be lost.
When the owner activity/fragment is finished, the framework automatically calls the ViewModel's onCleared() method so that it can clean up the resources.
Here is a code lab that you'd check.
I have another one question about transfering data from Activity to Fragment.
In my activity I have next situation: one part of UI is situated in Activity, and another (more dynamic part) is situated in Fragment.
The data which I need to populate my UI elements in Activity and Fragment is on server. To get that data, I am sending request to
server in Acvitity's onCreate() method. In Activity's callback method: void onDataLoaded(List<MyObject> dataList) I get data from server.
And in this method I am creating my Fragment and setup data to it. I am passing data to it through the Bundle object duding creation. Everything
is ok with this. But the issue is in next: on network reconnect I need to load data from server to be sure that all data is up to date. And of course I
need to reinitialize data in Activity and Fragment. But I don't want to fully RE-CREATE fragment. I want just to setup new data to it's fields.
How can I do that properly? Is it a good way to to keep reference in my Activity to that Fragment and call some public method: myFragment.SetMyCustomData(List<MyObject> dataList) ?
I understand that the best way to load data from server in my fragments onCreate() method, but I can't split it into two API calls and I need that data in Activity as well.
Thanks.
Well this is not a transfering problem . Anyway you can use Event Bus for easier communication from Activity to Fragment and vice-versa. It is very easy to use . And as for your problem I belive you are not doing what you need in the right time .
https://github.com/greenrobot/EventBus
I have a fragment that is always visible. I don't understand why I should use bundles to pass data to it from activity.
Most of the questions here recommend this method of passing data:
Bundle bundle=new Bundle();
bundle.putString("name", "From Activity");
Fragmentclass fragobj=new Fragmentclass();
fragobj.setArguments(bundle);
I prefer creating Fragment object in OnCreate function of activity and then use this object to display fragment(FragmentTransaction.add). As I have refence to this fragment I can create create function showName() in it and call it from activity like that:
myFragment.showName("name");
Is there anything wrong with this approach?
The Android documentation states:
Every fragment must have an empty constructor, so it can be instantiated when restoring its activity's state. It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated; instead, arguments can be supplied by the caller with setArguments(Bundle) and later retrieved by the Fragment with getArguments().
That's why it's better to use a bundle and set the parameters of the Fragment this way, it's easier for the system to restore its values when the fragment is re-instantiated.
Now, I wouldn't use myFragment.showName("name"); because you don't know if the lifecycle of the fragment has already finished (attached to the activity and inflated the views), so instead, I would call the showName("name") in the onActivityCreated or onViewCreated callbacks.
Applications should generally not implement a constructor. The first place application code can run where the fragment is ready to be used is in onAttach(Activity), the point where the fragment is actually associated with its activity. Some applications may also want to implement onInflate(Activity, AttributeSet, Bundle) to retrieve attributes from a layout resource, though should take care here because this happens for the fragment is attached to its activity.
There's nothing wrong with this approach for setting one off data values, you just need to be careful to make sure that the view that you want to set your name on actually exists at the point that the showName method is called.
Part of the reason that using Bundles to pass information is popular is that they can hold all types of data using keys and also they can easily be used to pass view states around during device rotation. Ultimately it's a matter of preference and exactly what your use case is.
When app is in background, the Fragment can recreated (eg: by change the theme (light/dark), language, ...).
So if you dont pass data use Bundle to Fragment, your Fragment will not have this data when it recreated
It might be an easy question but I have been working on it for hours and couldn't solve it. Sorry if it was asked before.
In my activity I have 2 Fragments. In one fragment I am getting JSON from server and putting in ArrayList. After putting in ArrayList I have to add another fragment passing first value in ArrayList.
Here is the problem, I want to add Fragment when my ArrayList is completed, after it got all values from server. I am making service call in my onActivityCreated() method, server call is happening in another class and I am getting Bundle in a method called onRequestFinished() and I am putting JSON to ArrayList in this Overridden method.
P.S. I tried to put AsyncTask but I couldn't make it since I have to wait the response from onRequestFinished() method.
How can I handle it and complete Fragment Transaction after filling my ArrayList?
Thanks
I suggest using startActivityForResult in the first fragment. When the parent activity receives the onActivityResult it can then start the second fragment. There are plenty of examples of how to do this on SO and elsewhere.
Even if you do not want to start an activity, you can use the same mechanism to communicate back to the activity when your first fragment has completed e.g.:
Is there a method that works like start fragment for result?
Alternatively you could of course just implement a callback mechanism from your first fragment - but personally, I like the onActivityResult approach.
I have an ViewPager with 4 fragments,
at the last fragment I want to make a validation and save the values that was inserted in the previous fragments.
I tried to override the onSaveInstanceState and save a Bunble with the data but the method not getting a call (only when the screen goes off).
How can I save the data and access it from the parent activity?
I think given your requirements you would be better to pass a model object from the Activity to the each of the fragments in turn. Each of the fragment's would store the data required in the model, and the once the last fragment is complete, it can be validated.
As a side note, I believe onSaveInstanceState is used for storing the current state of a Activity / Fragment so that it can be reinitalised without having to call possible long running background tasks rather than a way to share data.