I have to download "raw" data from the server every N seconds and then deliver it to fragments (which are inside ViewPager). Every fragment has to do its own computation on the data and then populate own RecyclerView.
I have one idea how to achieve that:
Activity's AsyncTaskLoader downloads data, store it and then
broadcasts an Intent that new data has come.
Every fragment has its own AsyncTaskLoader and connected broadcast receiver.
When fragment's Loader receives information about new data, get it form the activity, compute and deliver to RecyclerView
Is it the proper solution? Is there simpler approach to my problem?
You can use a Service which contain a Runnable code to download "raw" data from the server every N seconds.
Save received data in Singleton, and you can compute and deliver directly to your RecyclerView's adapter
AsyncTaskLoader in the Activity is a good idea, but I would simplify communication with the fragments by using a message bus instead of broadcasting intents.
Related
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
We are using Retrofit and Activeandroid for my project.
Currently we are facing an issue.
The pattern which we follow in our project is, We get data from server and save it into local database and after data saved we call routine which fetches data from database and populate UI this all happens in single Activity..
Now we have an activity which makes 3 server request, and due to which the amount of code in activity increased.
We are trying to reduce Activity code by creating fragment for the activity and giving responsibility of fetching data and displaying data to Fragment. Rest call will be made by activity. Now once the data is loaded from all the 3 request we need to inform fragment about data is loaded, what is the best way for this.
And is it even possible to send data to fragment once it is loaded.. or the approach we are following is not correct..
Please guide us on this..
Edit1
I read about EventBus. Can event bus solve this problem or it will effect the efficiency.
If you are storing those Fragment instances in your Activity then it will be much easier.
1) Create loadNewdata(DataType data) method in your Fragment.
2) Pass the data into the Fragment after getting response from server in your Activity
((YourFragment)fragment).loadNewdata(yourData);
I would suggest to use Otto.
By this you do not need to store your data in local db(if you don't want it).Just simply post your responce whenever you received from rest API. As Otto also provides the functionality of sharing custom objects between fragments/Activity. It also helps you to make your code modular.
You will find a working example here & here.
You can use Interfaces for this and send data to activity.when response come back pass reference of to show which fragment data needs to be populate the UI.
I have a viewpager fragment setup, and I have an AsyncTask run at the start of the activity to load some data from a JSON get (the data it pulls only needs to be done once, and all fragments will use it). The problem I'm having is I want to take this data from the AsyncTask, and have it be the data that all of the textviews pull from in the fragments.
What would be the best way to load data from an AsyncTask and then have the fragments reference that data. You cant just have the views reference the data from the get-go as it Nullpointers, and I'd really like to avoid having to reference every single textview in the OnPostExecute of the AsyncTask if I had it in the Parent Activity.
Just decouple the storage of the data from the view(s). In that way it will be easyer to handle the download of the data and to show it in the various fragments once the get is completed.
The basic idea is: launch the download in a background thread decoupled from the activity (service or intent service), then update the data a storage (sqllite if it is complex, shared preferences or even a singleton object, even though I don't like the latter approach).
Once the get is performed, inform the fragments that the data is available. Still, you have a lot of options here. If you decided to host the thread / asynctask inside a service, you can bind a callback to it and then notify all the fragments interested, you can use a (local) broadcast message that you can intercept using local broadcast receivers, or you can even use a message bus such as otto.
Finally, I really recommend to use an intent service to perform the async job. It's the easiest way to do any one shot operations without having to deal with service creation and/or with activity configuration changes.
Not sure if this is the "best" way, but what comes to my mind first is the famous Observer pattern.
Create an interface called Observer with a single method called
notify()
Implement this interface in all Fragments that want to be notified when the data is ready
Hold a List of Observer objects inside your AsyncTask
In onPostExecute(), traverse this List and call notify() on every Observer, passing the appropriate data
React on the notification inside your Fragments given the data
This a very rough description of this solution, but I hope you get the idea.
I need an advice to the best way retrieve and show some data.
I have a service which compute and saves data from GPS (every 500ms) and JSON (every 30 sec) inside a sqlite localdb.
The data is stored in two tables: header (updated every time) and detail (add new row every time).
What I want to do now, is use this data (it is about 20-25 variables) saved in header table and bind it to an activity and some fragments.
The main activity is composed by a main fragment and a
FragmentStatePagerAdapter (with at least 3 fragments loaded inside)
Which is the best way to show this data?
I thought to:
- Create a "Bundle" and use handler and messages (Service -> Activity, Activity -> Fragments).
- Create a "Bundle" and use a local broadcast to send and receive data in every fragments loaded.
- Use a LoaderCallbacks and SimpleCursorAdapter with "FLAG_REGISTER_CONTENT_OBSERVER" in every fragment and retreive and show data directly from database.
What do you think is the best one?
(In terms of performance, best practices and low memory consuption)
Thank you in advance and sorry for my english..
in case of
Use a LoaderCallbacks and SimpleCursorAdapter with
"FLAG_REGISTER_CONTENT_OBSERVER" in every fragment and retreive and
show data directly from database.
you will do unnecessary retrieving data from database, while you can simply receive it from broadcast.
I think the best way is to register broadcast receiver and take "ready for display" data from your service.
I have a List of items that I want in a ListView, and I can make it work with setting a custom adapter every time the List grows, but the program flow is kind of weird and I have problems with persistence. (If I switch tabs, the UI gets rebuilt with an empty ListView.)
Now, in my day job I'm a C# developer, so when I look at this problem I see a WPF ListView bound to an ObservableCollection. Does Android/Java have something like that, a "fire and forget" connection between a UI element and a data structure?
You don't need to replace the adapter every time you change the data. The adapter "adapts" between data and view. There is no need to change the adapter as long as the way it adapts does not change.
Activity / Fragment lifecycle is not necessarily the lifecycle of your data collection. You can for example make a singleton data collection somewhere and use an adapter to display that collection all the time. Call .notifyDataSetChanged() on the adapter if you changed the data.
A persistent data collection in Android is probably best backed by a database. Take a look at LoaderManager & ContentProvider to provide and load data then displayed via CursorAdapter.
There is no automatic way of keeping a bunch of data available outside of your Activity / Fragment / .. lifecycle and it can get quite complicated but that's basically what you have to do if you want to keep data for longer than a given lifecycle. Singletons, Activity#onSaveInstanceState(), Activity#getLastNonConfigurationInstance(), Fragment#setRetainInstance(), ... are useful utilities to keep data in memory, databases are good for persistent data.
You have to do a little bit work yourself but it's possible. Use a ContentProvider as your DataSource. How the data is stored is up to you. I would prefer a SQLite-DB. A content provider has the possibility to add ContentObservers. (See this related question.)
You can write a CourserAdapter to fetch the Data from your content provider. And your ContentObserver should call notifyDataSetChanged() on your adapter. This closes the circle and your UI refreshes itself.
In Addition to zapls answer:
You can also write an adapter which contains a BroadcastReceiver. When your DataSource changes you can send a LocalBroadcast. The broadcast handler just calls notifyDataSetChanged() of your adapter. I think this would work around most of the lifecycle problems because only active elements will get the broadcast.
The google documentation has an example for such a solution.