I have an android activity that needs to run six asynctask classes.
I created my activity and it works fine, but with those 6 classes my code is so hard to comprehend or edit.
Maybe its dump but i am new in android so what i need is to know how to simplify my code a bit: is there a possibility to make all async tasks in one class knowing that they have different functionalities
You can have one Async Task only and do different things in it by passing a functionality ID, if you may, as a parameter.
Although, I strongly recommend you to create 6 different files, each containing your Async Task class (if they have truly different functionality) and put them in a package "Async Tasks", if you may.
If, for instance, you need to do different sort of requests to a server, you should only have one Async Task, different parameters (such as URL, post parameters, etc) and handle the result different in your onPostExecute method according to the type of request you have done: send an event to your activity that calls the proper method to handle the result.
You can use this technique to manage you more-general Async Tasks
is there a possibility to make all async tasks in one class
Yes, but don't. You mention "simplifying" your code - putting more functionality into one class will make it difficult to understand what that class is responsible for.
The better option would be to add 6 different implementations of AsyncTask, and create new instances of them in your Activity. The names you use for the classes should represent what they do, and they should do as little as possible.
You could move your AsyncTasks to separate files. You could pass the Activity to your AsyncTasks constructors.
Might be you also could combine some of your tasks into one.
Related
So I have an app that will make multipe HTTP Post/Gets
E.G. Login, getThisData, getThatData, sendThis, sendThat
Is it better to have a seperate AsyncTask to handle each one
Or one async task and process them differently with a switch in onPostExecute and doInBackground
Cheers
Short answer is yes you should create a new AsncTask for each call.
And if you interested, the long answer is;
According to the Android's Asynctask documentation,
The goal of the AsyncTask is to take care of thread management for you and you should not worry about the threading mechanisms.
The Android Platform handles the pool of threads to manage the asynchronous operations. AsyncTasks are like consumables. The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Happy asynchronous coding! :-)
It depends on whether the tasks are independent on each other or whether they are interrelated. If independent you can handle this through the same async. For ex if you need some data from your login response and pass that value to getthis task you better use separate async.
Make login a separate async, getthis ,get lthat sendthis sendthat can be in one async.
You'll probably want to separate them, especially if their functionality in the pre/post executes differs. Try to organize your code into logical blocks. For example, if you have an Async Task to Login, and an Async task to, for example, download lots of document data via JSON, they will want separate Async tasks.
However, lets say you have two separate API calls that return similar or partially the same data - if one returned the details of a file (name, size) and the other returned the same data but was a revision of a file - you could switch these in the same ASYNC because the post execute is going to perform the same (or partially the same) code to extract data from the JSON.
If you want to create one instance of AsyncTask, and execute() it several times, no:
Execute AsyncTask several times
If you are asking about designing: whether you should write one class to get different kind of data? It really depends on your circumstances:
If these HTTP call supposed to be sequential, you can put them in one AsyncTask class.
If they have lot in common, just point to different URIs, you can write a call(String uri) method, and invoke that method in your AsyncTask. This case, I think one AsyncTask is also enough.
I would like to have all my Activities (7 to 10 different screens) submit data to a "controller" (sorry if I'm miss using the term).
Inside said controller data would either be uploaded or saved to data for uploading when no internet.
The controller would do checks and processing such as:
Checking for valid session.
Attach other needed credentials before
upload etc.
Session/User data would be stored in a Shared Preferences file the controller has reference to.
My goal is to have Activities do nothing more than collect the data and call the appropriate method (with a data object) asynchronously. The controller would know how to process the data for uploading or saving in the database.
Would placing these methods in an extension of Application be a bad idea?
It was mentioned that depending on application size this is feasable, but there could be better solutions.
Depending on the size of your project, that would be a suitable idea. However, there are some other ways you should know before choosing the method you're actually implementing:
Using a ContentProvider for your data, an AccountAuthenticator and then sync to the server using an SyncAdapter. Advantages are a good abstraction, independence from activities and many built-in features (for example: Android executes your code without a big battery life impact). However, implementing all the stuff is quite much work at first. If you don't want to use the ContentProvider, the same technique works with a stub implementation as well, the same goes for the AccountAuthenticator.
Using a Service, probably IntentService, for your uploading needs. Advantage is that the Service has an independent lifecicle and thus is not directly related to your Activity; a Service can get restarted if it has been killed by the system. Still more work than just using some static methods.
Using a static method as you're proposing it (in your case, the Application object; not completely static, but compareable). Quite easy to implement, probably the best way if there are similar tasks in multiple activities; your AsyncTasks can send their result directly to the activitiy that started it. However not suitable for long-running tasks.
Implementing within the Activity; If code is only used once; listed for completeness only, not for your case. Basically the same as using a static method.
These are the ones that popped into my mind, there might be some others, too. Feel free to add/suggest additonal ones.
Background
I've heard that there are some new solutions for loading data in the background which are more recommended than AsyncTask (like loaders).
The problem
AsyncTasks are great and easy to use. However, it has some limitations:
The class itself has to be modified since it's limited by the number of pending tasks (about 256 or so). Of course, in a listView's adapter, I always cancel a task if it's not needed(for example when I need to update a view that was used for a different item).
I also have to cancel them all (or handle in a different way) when the activity/fragment is being re-created.
Because of 1&2, I need to manage them and have a reference to all of them
AsyncTask uses a queue of tasks, and sometimes I need to use a stack instead, so I had to create my own class of AsyncTask that uses a stack instead.
The question
Are there alternatives for AsyncTask?
I know this was asked in some posts before (like here), but I was thinking if there is a new general way to load data in the background which replaces the asyncTask.
About Loaders, I think the idea is that they are used for databases and contentProviders, but can they also be used for loading (for example) data from the Internet (like images files) ?
There is also a nice sample made by google (here, called "bitmapFun"), which according to what I see uses AsyncTask (and even extend it, maybe because of the same reasons I've mentionsed) . But maybe I'm missing there something too?
Maybe you should consider reviewing your approach, the need you have for performing several updates depending on the view and cancel all the pending tasks from the previous views gives the impression that you are performing the load of data individually for every view that needs to be created.
In a list view with a list adapter, the usual approach is to load a portion of the data (either as list of ValueObject or as Cursor from multiple database rows) paginated on demand or in one goal, not item by item. So if you wish to update the next page, you basically perform one single operation, either using AsyncTask or Loaders to fetch the new items to the model then making it available for the UI to display them. This way, you will be applying MVC, and you won't have several pending tasks to cancel and control, and your structure would be more solid and easier to manage.
About the alternatives, If you're dealing with database, the most straightforward way is to use the CursorLoader, i.e. the loaders instead of AsyncTask, but if you're dealing with data that comes from the network or filesystem, you're kinda free to choose from the variety of other options available. AsyncTask is much more simpler to use, mostly recommended for simple things or one shot queries. But you can also use Loaders for such tasks as well, see AsyncTaskLoader.
Yes.
Loaders are managed AsyncTasks. If you are not using a Loader, you are probably missing the management that they require.
AsyncTasks (and Loaders) are a pretty bad way to get stuff that is off the device. To get data from a remote server look into using an IntentService. See: https://www.youtube.com/watch?v=xHXn3Kg2IQE
AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask. See the http://developer.android.com/reference/android/os/AsyncTask.html for more info.
An alternative to asynctask is robospice.https://github.com/octo-online/robospice.
You can get started with robopice here. https://github.com/octo-online/robospice/wiki/Starter-Guide.
A sample of robospice at https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result.
Some of the features of robospice.
1.executes asynchronously (in a background AndroidService) network requests (ex: REST requests using Spring Android).
2.is strongly typed ! You make your requests using POJOs and you get POJOs as request results.
3.enforce no constraints neither on POJOs used for requests nor on Activity classes you use in your projects.
4.caches results (in Json with both Jackson and Gson, or Xml, or flat text files, or binary files, even using ORM Lite).
5.notifies your activities (or any other context) of the result of the network request if and only if they are still alive
6.no memory leak at all, like Android Loaders, unlike Android AsyncTasks notifies your activities on their UI Thread.
7.uses a simple but robust exception handling model.
This is somewhat design specific question but I am looking for right advice.
In my app I have 6 pages A,B,C... each of which will download data from server and display it. In this case among below mentioned approaches which one will be good.
1.For each A,B,C write inner asynctask class
2.write separate asyntasks like asyntaskA,asyntskB etc for each of these activities
3. write a single asynctask and route request of each activity through a requestcontroller class which creates instance of asyctask by passing context,url parameters
If the second approach is taken, is it possible to run one Activity and another Activity in onpause state while its asynctask still running?
In each page, if you are doing the same kind of operation (As in this case, downloading data and displaying it), you need not write separate AsyncTask classes. Just create as much instances as you need and call the execute() method. AsyncTask class will handle this in thread safe way.
Second part of your question is bit unclear, but if you meant switching between activities, it is possible with multiple instances of a single AsyncTask. You'll need to save and restore the activity states.
If the operation you performing is time consuming, say more than few seconds, it's not safe using an AsyncTask. The better option will be a Service.
There's no problem with multiple AsyncTasks. In one of my apps I have a grid-view with images and there's an AsyncTask for every image loading and generating a thumbnail image. They all run in parallel quite nicely.
I've made an application that Fetches a Webpage from the internet, based on user input, wich worked. The fetching goes in different steps: post with String from edittext as parameter, after some parsing this returns an Array of names wich are displayed in an AlertDialog. When the user picks one, it makes another post with that String as parameter.
This works, but now I want to make it Threaded (or similar), so that the UI doesn't get unresponsive.
I tried Threads, Runnables and AsyncTask, but I just cannot find out a construction to get the fetching in a single Thread, and also be able to return that array and pick a name, WITHOUT making a new instance of my HttpClient. This would erase Cookies you see...
I've spent about a whole week to figuring this out, but just don't see it :(
So anyone got an idea? thanks !
For each of your HTTP accesses, you can create a separate AsyncTask subclass, then instantiate each one of them in turn, and execute them. On the web there are many examples on how to use AsyncTask to access HTTP, e.g. here or here (just google for something like this).
The main idea to grasp there, is to do all the network-related operations inside the doInBackground method body of the AsyncTask.
As Ted Hopp said, you can let the HttpClient instance be a private member of your Activity (or whatever class holds the two AsyncTasks), so that the first AsyncTask will create it, and the second one can just use the same.
You can use two AsyncTask subclasses, one for each request. Give the subclasses access to a variable in your activity class that stores the HttpClient object.