I have three fragments. Fragment A- contains a ListView to show list of items fetched from API and Fragment B to show the detail of List item.The fragment C is a separate fragment.
Fragment A contains 100+ items which takes time during fetching from Api.
When user comes on Fragment A, the Api call is fired (fetching records), Now after few seconds if user switch to Fragment C; it comes up and fragment A ondestroyView is called. Now when user comes back to Fragment A the api call is again fired.
What i want to achieve is that if user comes back to Fragment A should not send the call again but it should keep continuing the last process or the fragment A must be keep processing its work flow if i have switch to Fragment C.
Can any body please suggest a good way to achieve this?
The base algorithm is:
Load data in separate thread.
Store it in db.
When load finished, generate an event(with EventBus for example).
Subscribe on this event and show the content with CursorAdapter and CursorLoader when you need it.
So, you have thread-safe and configuration change-safe way to load, store and show the data without blocking main thread and unnecessary server calls.
Fetch the data in an IntentService. When the data is fetched fire an event.
On your Activity (the father activity for your fragment A, B and C) listen for the event and store the fetched data within your activity.
On your activity, check if fragment A is visible. If it is visible, pass the data to your fragment.
This way you activity lifecycle will handle the availability of your data, e.g. as long as your activity is alive you don't need to fetch for the data again, which is what you are looking for I presume.
I didn't test this but I don't see why it shouldn't work.
PS; Don't use asynctasks. They are bad, very bad. Check here why.
Try Retrofit for your network calls.
Related
I am following MVP approach, and I have an activity containing 4 fragments. On App launch activity makes network call, and passes data to fragments.
In one of fragment i have recycler view, and it has Swipe to Refresh.
When user swipe to refresh i need to make network call from fragment, which i learnt is not a good idea, and also i am following MVP approach, so activity has the list of methods to execute in presenter, and presenter decided whether to grab data from local repository or remote.
So what should i do to perform swipe to refresh operation from a fragment.
Should i call activity method, and perform network call from there, and re pass the updated data to fragment, or is it fine to make a network call from fragment.
The answer is neither the Activity nor the fragment. The fragments and activities shall never "fetch" or "handle" data. Only display data. And deal with activity lifecycle with regards to this.
If you want to know further this will be a good read for you.
What is the best practice to notify all the fragments that are in backstack on some change?
I try to use EventBus and every Fragment subscribe to the event, then when change is happening the main activity send post event to all the subscribers.
Only onDestroy I Unsubscribe the destroyed fragment.
I don't like this solution because if there are many fragments in backstack, it can be heavy + lots of listeners simultany.
my application, has infinity drill down, from one fragment you replace to other (and add to backstack) and you can replace again (and add to backstack) and so on..., with no end.
A possible solution is to put some data into shared preferences and read it in fragment onResume.
Or you could put that informations in other parts, like configuration servers or external service
Obviously if these fragments belong all to the same activity you can put informations into your activity, then you can read it from that attached activity.
For remote fetched data
You may put your data into a singleton class only responsible to keep data. Keep in mind that in android a singleton could be destroyed in some limit cases, so when your fragment come back in foreground check if the singleton is empty and eventually repeat your fetch call
You can see an example here
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 scenario and I an not sure on what path to go.
Scenario
The app has a Home activity which displays various fragments. The data in the fragments can come either from the web or a local database and is retrieved using an asynctask.
From what I saw, I have 2 alternatives:
Put the Asynctask in parent activity and then use fragment.newInstance(parameters) to pass the result to the fragment. However, if in my asynctask I need to update the progress or some info on the fragment, each time I will have to call newInstance with the new set of parameters.
Add the fragment and put the asynctask in it, in this way when progress is needed, I can update the fragment's views, as I have access to them + when the asynctask is done, I can populate the list with the info.
What would be the correct approach ?
LE: actually for point 1 in order to update the fragment I can call fragment's public methods after I find it with findFragmentById in the parent activity
A better way if you have multiple tasks would be to use an IntentService :
http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/
You would have a better control to what you're requesting and what you want to cancel.
I would go with the second approach.
My primary reason though would be to avoid the issues that can happen on screen orientation change while the AsyncTask is working.
I would go with method 2, but take it a step further.
Have a separate fragment to run your async task. This way, you can handle any configuration changes (not just rotating screen) without any issues.
In another fragment, you can display the data. You can pass the data from your async task fragment via callbacks to the activity, and have the activity call a method in the display fragment to update the data.
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.