I am working on an Android application and I have a question. I have a listener class that runs on back ground periodically and get data from my server. I want to add that data into a data structure in the main thread. In this case, I am not touch the main U.I. but I was wondering if I should use a handler to add the data into the data structure in the main thread. Or can I just set the data structure as static and access from the listener class to insert the data. Which way should I do? Thanks in advance.
One way to do that (but there are others) is to use a list view and a cursor (it means you should use a database).
When you receive data from server (in your background thread), you add them to the database.
On the UI thread, you register a ContentObserver to be notified when data is added. When you're notified, you just have to requery
If you don't want to use a database, you can then send a Broadcast (see BroadcastReceiver) in which you can add data.
Related
I have an Activity that has a fragment which is full screen RecyclerView. The fragment implements LoaderManager.LoaderCallbacks<Cursor>.
I have an IntentService that goes out and fetches data from an API, deletes any existing data in the local SQLite database, and then stores the new data all via a content provider.
The Loader then Loads whatever data was put into SQLite into the RecyclerView.
My question is:
Where would be the most efficient place to put my code to fire off the IntentService?
Just wondering if there are any conflicts that could arise if placed in an inappropriate place.
Currently, I have it as the last lines in OnCreate() in the Activity:
// Fire off service to get data
Intent i = new Intent(this, MyService.class);
startService(i);
Other places I was considering putting it:
In the OnCreate() in the fragment.
In the OnActivityCreated() in the fragment.
In my opinion, running it in onCreate of your activity is just fine, however in this case, your RecyclerView may present outdated contents to the user. So you should somehow notify your RecyclerView from inside that IntentService and make it to re-query the database.
Running that service in onCreate of that fragment or OnActivityCreated() wouldn't give you any performance gains.
To bring a better user experience to your users, I would suggest you that use pull-to-update libraries to fire off that service and update the list whenever the user drags it down. Just like Instagram app.
First, I would like you to take a look at this answer in SO that also has links to android documentations.
Also from the documentations, an IntentService has few limitations:
An IntentService has a few limitations:
It can't interact directly with your user interface. To put its results in the UI, you have to send them to an Activity.
Work requests run sequentially. If an operation is running in an IntentService, and you send it another request, the request waits until the first operation is finished.
An operation running on an IntentService can't be interrupted.
However, in most cases an IntentService is the preferred way to perform simple background operations.
I have created a quite nice implementation of a Broadcast/BroadcastReceiver where I am pulling down information via a Service from a Web API, Broadcasting the result of the received data and then changing the UI when the OnReceive function is called in the Activity which updates the UI.
The way I am updating the UI though is by passing the 'id' of the row to the database and then pulling the data out again.
This doesn't seem very optimal as I have to access the database twice. Once to save and once to retrieve. How can I optimise this? How can I optimise the process of updating the UI without having to go to the database again?
Options which I have researched:
Send a Parceable/Serializable object in the Intent when Broadcasting
Saving the retrieved data in a static class and using that data when onReceive is called.
Thank you in advance.
After filling a ListView from local SQLite I want to fetch data over the network from a remote Database in order to retrieve new Data, and show it in the ListView so that the local SQLite Database is just a fallback method in case of no internet.
I was using a different Thread to insert the network-fetched data into the SQLite and then re-fill the ListView list.
Naturally, the app crashes because at some point the second Thread is removing every item on the list (to add new ones) and at the time, the UI Thread is trying to access an index who's been deleted by the secondary thread.
Since this is for academical purpose, the idea is not using external/custom libraries, so what'd be a good approach that doesn't include custom libraries?
Wrap the database in a content provider. Not difficult to do, since you already have the database. Instead of writing your own Thread, use an IntentService to fetch the network data and write it into the content provider.
In your Activity, use a CursorLoader to load the data from the content provider in the background. CursorLoader includes an implementation of onDataSetChanged(), so every time the content provider is updated, the Cursor will be reloaded. Every time the Cursor reloads, swap the new Cursor into the CursorAdapter that backs your ListView.
To communicate between the IntentService and your Activity, do two things:
Send a local broadcast Intent (using LocalBroadcastManager) from the IntentService to the
Activity when the network download completes. If your Activity is in the foreground, it
will get the broadcast immediately, and you can fire off CursorLoader for the first time.
Also post a notification from the IntentService. In this notification, include a content
Intent. If your Activity is in the background and the IntentService completes, the user
sees the notification. He or she can then click the notification to go back to your
Activity. You can fire off CursorLoader if you need to, or what until CursorLoader restarts automatically.
Your issue points out the desirability of rethinking app structure when you're programming in Android. Android apps aren't linear; they're more like mega-objects that interact with each other according to their current state. For this reason, you should avoid writing your entire app in one Activity, or writing it from the top down.
Also, there's hardly ever a reason to create a new Thread() on your own. Android offers plenty of classes that handle asynchronous processing for you. If you find yourself coding a Thread() or run(), be wary.
Only update the ListView on the main application thread. For example, instead of a Thread, use an AsyncTask, where you do your disk and network I/O in doInBackground() and update the ListView in onPostExecute().
Because the data shown in ListView is shared, you have to protect it via synchronization. You should write the code synchronized (data) {// data operation} in different thread in case of crash
To me is diffucult to understand which the right workflow is to download json data and show them in a ListView.
Currently i am using an AsyncTask to download and parse data that is shown using an ArrayAdapter. The problem is that AsyncTask doesn't survive to activity restarts.
So I am wondering if services are a better solutionbut how to pass data to the ArrayAdapter? Should I always use the db as middle layer to store and retrieve data?
So which is better? AsyncTask in retained fragment or service using db?
Thanks
I use a service to do http data retrieval and storage into sqlite db. Once the service has stored the data (or if there is a problem) I then fire a broadcast. My Fragments / Activities listen for these defined broadcasts and then act appropriately.
I find that this is a very clean solution and avoids the problems of leaking asynctask references on activity teardown / rotation etc.
The most simple solution would be to return your current AsyncTask in onRetainNonConfigurationInstance or use a Fragment with setRetainInstance(true).
You can access the AsyncTask in inCreate with getLastNonConfigurationInstance
It actually depends on the requirement of what exactly the Activity needs and how long can the data be displayed without hitting the service again.
One approach to the above mentioned problem is, hit the service get the json data and store it in database. Now fetch the data from database and display it in the Activity. You can now implement a service to refresh the data when required. The service will simply hit the web service and update your db content as and when required.
I have a service that connects to a server (regular TCP socket) and receives data updates in a thread. I want to store this data (after a bit of processing) in a model that can be accessed by multiple activities (typically ListView with custom ArrayAdapters). In the activities I use bind to get a handle to the service so that it can access the model and register as a listener to get notifications when the model change.
The problem is that access to the model needs to be thread safe. First I thought I would call runOnUIThread with the incoming data inside the service for updating the model, but the service does not have that routine. Any other way to update the model inside service from the UI thread? Or is there a better architecture/pattern that I should use?
No response, but this is what I ended up with: Every on... call (e.g. onCreate, onBind etc) are run on UI thread, so I ended up creating a handler in onCreate and posting to that handler to update my model on the UI thread.