I was going through the android docs for Efficient Network Access. I got the data prefetching part as well as the batch transfer approach, basic crux behind both of them being
Don't keep the network radio in active state all the time. let it go to stand by state at regular intervals
However, proceeding to the next section, Reduce Connections, I am still not clear with some of the statements. They are:
Reusing connections also allows the network to more intelligently react to congestion and related network data issues
and
it would be more efficient to make a single request for every news article to be returned in a single request / response than to make multiple queries for several news categories
and
A useful compromise is not to close the connection immediately, but to still close it before the inherent timeout expires
Can someone please explain these statements in detail?
Related
I have been reading a lot about network operations with android and how to do it properly. The documentation suggests using Volley and it abstracts the process making the network request:
http://developer.android.com/training/volley/simple.html
As I use Retrofit in my app I thought that the best practice was to use Loaders as they behave well on orientation change, but I found this:
http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html
"Using a Loader to perform network requests isn't great practice, because (1) it means that your application will be hard on the battery (having to poll for new data from the network repeatedly each time you start the Activity, (2) there is no way to observer the network for content changes without polling it repeatedly, and (3) your application won't work offline."
(1) isn't particularly true because you can just resume the loader on activity creation. I don't think I fully understand point (2) and point (3) isn't a concern for me as there is no way for my app to work properly offline.
However, this caught my eye, again, from the same link.
"So my answer is to forget about using the Loader/AsyncTask combination entirely and to stick with a Service. The Service can poll the network for data every once and a while and insert new data into a ContentProvider. You can then use a CursorLoader to load data from the ContentProvider without it needing to know anything about where the data coming from."
Has anyone used this approach of using a Service to poll the network and populate a ContentProvider? I don't think it will work properly with my app as it uses a RESTful API that is constantly requested. I don't think it will be particular effective, but I might be missing something here.
Sorry for the long question. It is not a question exactly, but I wish to create a discussion around the topic.
I'm currently developing an mobile application and rest service. The mobile application executes lots of calls to the service even if no update is required and data didn't changed. In order to remove this overhead of rest calls I'm planning to implement GCM (Google Cloud Messaging).
My strategy would be the following:
Load all required data on application startup. When data change was recognized on server side a push notification will be sent via GCM to affected devices to make partial refreshes of data (via specific rest calls). Advantages of this would be less overhead at service side, because there are no unnecessary rest calls and a more fluid user experience in my opinion. Disadvantage is that the app is dependent on GCM Messages and that they arrive in time.
I'm unsure if this is the right strategy for this. Could someone maybe point me in the right direction and tell me if this is a good practice?
We could use more information before answering details...
I'm unsure if this is the right strategy for this. Could someone maybe point me in the right direction and tell me if this is a good practise?
I will consider for the sake of giving an overall answer that:
A - User is not always with the application "online", neither has network, not even a desire to have updated info at all times.
B - User is eletronicaly litterate enough to understand difficulties with the program.
With those in mind, then what would be a good approach is:
Poll relevant data, store them locally. At this stage, one would consider the relevant informations that user would have and store them, with a date flag.
Once a flag goes "old" (below your threshold), re-query that data.
Operations follow 2 directives... When observing a data, check its state, show the user if its recent or not, and if its not, poll it. If it is, if the user selects operations on it (POST mostly), re query the data.
This way, you have no static overhead, if users dont have the app on foreground. Also, should they use your "always online app", they understand that network is a necessity.
For a single screen, I have to show data which is not available from a single webservice call. I have to call three independent different webservices to get all the data to show in the screen. If I call three at a time, there is chance of getting false in poor connection and if I call one by one, then it will take long time and give poor experience to user. How to deal with this problem so that it gives best user experience and lowest chance of failure in internet connection.
I think this post would be off on UX Stack Exchange
Anyway, if your asking for something technical though, what we used before is implement a connection speed utility class (ConnectivityUtil) and provides a method hasFastConnection. See sample implementation here.
So when it detects a slow connection, we show a Toast saying something like "Your connection is a little bit wonky!" or any other. This would switch the blame to the user's connection rather than your app being slow.
We also increased our timeouts for this and if you have access to the backend, enable GZip compression and handle it appropriately on the client.
I'm using Fragments and LoaderManager. I have to launch an unknown number of tasks, and they might be run in parallel (otherwise I'd just reuse one and only one loader). For example, I have a listview, and each row might have a button to save the content of that row to a webserver. The user could initiate a save request on multiple items in parallel.
private int nextId = 0;
private void onClickListener() {
Bundle bundle = new Bundle();
bundle.putNextData(...);
getLoaderManager().initLoader(nextId++, bundle, this);
}
I could try bookkeeping myself, so create a pool of loaders manually and reuse them when possible, seems like it might be something already implemented by the API?
Thanks
I don't think you should use a Loader for saving data to a remote server.
Instead, use an IntentService or something similar to process a queue of "save" operations. This way, your communication with the web server can be batched, collapsed (i.e. multiple queued saves for a single item can be collapsed into one operation), and will live beyond the lifespan of your activity if need be.
A save queue processed by an IntentService (or equivalent) is also a great way to retry failed operations with backoff, since you can implement delayed retries with exponential backoff using AlarmManager.
An IntentService or bound service are always good approaches for that.
As Roman points, note that enqueuing several requests and called them separately is not highly recommended (it is very likely that you give a lot of work to the radio connection - when using data - which among other things drain your battery. Here is must-read about that)
I'd personally recommend to use a bound service with a queue of requests and a pool of threads available (that approach gives you full control for more complex network operations like in your case). There are more details on the approach here and a testcase working example over here.
Update us about your progress.
You are at the right direction, let me just help you a bit.
Reusing is indeed a good idea, and you do not have to worry about it because Android did it for you(Or Java actually ;)
It called ThreadPoolExecuter, you can start as many tasks as you wish and he will only open the predefined number of threads.(Best practice is trying to open as many threads as parallel network connection can be run on the device. From my research it is between 4 - 9).
And if you are trying to download same URL twice may be you can protect your self and open only one task for it.
I am developping an application that retrieves some data from a server.
I have two options:
Get the whole data set from the server and then work with it using the pattern 'singleton' to reduce the number of queries
For each query, get the corresponding data set from the server
What is the best choice?
In my opinion it depends.
It depends on the size of the data and if it even makes sense to return data that your user may not even need.
Personally, in my app that I am building I will be returning only the data that is required at that time. Obviously though, once I have the data I won't be fetching it again if it makes sense to keep hold of it for good or even just temporarily.
I agree with C0deAttack's answer. Your goal should be to minimize network traffic within the constraints of your app being a "good citizen" on the phone. (That means that your app does not negatively impact the user or other applications by using too many resources — including memory and file space.)
From the sound of it, I'm guessing that the data are not that voluminous. If so, I would recommend caching the response and use it locally, thus avoiding repeated queries to the server. Depending on how often the data changes, you might even consider making it persistent, so that the app doesn't have to query the server the next time it starts up. If the response includes an estimated time before it is considered outdated, that would help in establishing an update schedule. (Google's license server uses this idea.)
P.S. I don't see that this has anything (directly) to do with a singleton pattern.
How about storing your data in an sqlite database and do your queries with sql? Since you get sorting and ordering for free, it can help you writing less code. Also you have instant offline functionality if your user has no internet connection. :)