Generic asynctask for ws calls in Android - android

I'm using AsyncTask class to execute WS methods. I would like to have a generic async task class to call any method in the WS.
I create a set of classes that works fine but the problem is when I have to update the UI. I know I can create the async task with a reference to the Activity class and then execute the desired method, but what I want is the method to execute to be also a parameter.
Otherwise I have to implement a new class for each method which interacts with the UI because each action is different depending on the method.
Provably the solution is to use Listeners combined with parameters but I didn't find a complete example of how to use this.

In Java, you cannot pass a method as a parameter, but you can pass an object that extends or implements an ancestor and overrides that method. The Command pattern uses this concept (http://en.wikipedia.org/wiki/Command_pattern).
Here's an idea of the approach:
private static interface Command {
public void execute();
}
public static final class MyWsCommand1 implements Command {
#Override
public void execute() {
// TODO your WS code 1
}
}
public static final class MyWsCommand2 implements Command {
#Override
public void execute() {
// TODO your WS code 2
}
}
private static class GenericAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Command command;
public GenericAsyncTask(Command command) {
super();
this.command = command;
}
#Override
protected Result doInBackground(Params... params) {
// TODO your code
command.execute();
// TODO your code
return null;
}
}
private GenericAsyncTask<Object, Object, Object> myAsyncTask1;
private GenericAsyncTask<Object, Object, Object> myAsyncTask2;
And use those in your code:
myAsyncTask1 = new GenericAsyncTask<Object, Object, Object>(new MyWsCommand1());
myAsyncTask1.execute();
...
myAsyncTask2 = new GenericAsyncTask<Object, Object, Object>(new MyWsCommand2());
myAsyncTask2.execute();

by WS , you mean webservice?
asyncTask is not meant to be used for such long tasks . they are supposed to do small tasks . things that take (approx.) less than 5 seconds .
if you wish to do very long tasks , use a simple thread and consider putting it in a service.
also , in order to communicate with it , you can communicate with the service , and when you need to post something to the UI thread , use a handler .

The most close answer is this
You can choose the method in the same UI which waits until the background process ends

I would use Async, and I did on a production implementation. The issue you'll run into is doing more logic in the doInBackground because if you watch your debug build any time you see it say "Skipped X Frames" you may want to do a lot of post processing in doInBackground still.
Using an interface is the best approach, it's how I implemented my Async class. full.stack.ex hit the nail on the head with that answer. That answer shows a clear, simple, powerful way to extend Async and use it for your purpose.

Related

Android: AsyncTask using Command pattern ... How Can I publish the progress?

I would like a more generic and easier approach for starting methods in the background. So the Command pattern looks like a good candidate.
#Full stack ex describes an implementation of the Command pattern in his post with AsyncTask .
The problem is : how can I publish the progress in my method, executing in the background, via the normal AsyncTask Progressdialog or callback?
Normally we use publishProgress( progress) ... but that is not possible. publishProgress is of scope 'protected'. Calling directly onProgressUpdate( ) updating the dialog is of course not possible, crossing the line of background process and UI process.
How can I use this or similar approach AND publish progress (via
private static interface Command {
public void execute();
}
public static final class MyWsCommand1 implements Command {
#Override
public void execute() {
// ------- TODO YOUR CODE ---------
publishProgress( 90); // similar to this
}
}
private static class GenericAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Command command;
public GenericAsyncTask(Command command) {
super();
this.command = command;
}
#Override
protected Result doInBackground(Params... params) {
command.execute();
return null;
}
}
private GenericAsyncTask<Object, Object, Object> myAsyncTask1;
myAsyncTask1 = new GenericAsyncTask<Object, Object, Object>(new MyWsCommand1());
myAsyncTask1.execute();
publishProgress is of scope 'protected'
That means you can call it from a child class. A protected field or method can be accessed in the class itself, and any class that inherits from it. Your original plan should work.

HTTP helper class in a thread?

I am writing an app for android that connects to a server to get/post some xml data. I currently have a small class with static methods such as post(string URI, string body) and get() that wrap the httpclient calls to create a http post request and return the response. I am wondering if i should also have these method work in their own threads. Currently, i need to do a async task to call my Helper.post(..) method to connect to and get a request from a server. Is it better to just have the async stuff incorporated in the helper class to avoid having multiple repeated async tasks all across my app to just make post calls?
As a general principle it is best to wrap up repeated code so that you dont continually re-invent the wheel. Therefore if it is possible for you to wrap up the threading easily then it would be a good idea to do so.
This is not always very easy. Methods which get something from the network define want done with that data once it's been received. Usually you just return it. But if you're threading within the method then you have to push it somewhere. This leads to a lot of additional callbacks and you dont (in my experience) save much.
Rather than defining a bunch of static methods which do the threading for you, I would recommend you keep threading out of the static methods and define a bunch of abstract AsyncTasks instead. Each defines it's own doInBackground and leaves the onProgressUpdate and onPostExecute methods undefined. That way you get the best of both worlds - you re-use as much as possible (the doInBackground code) but are able to customize where the data is sent once received.
Example
Your static code:
public class MyStaticClass {
public static String getFoo( String name ) {
// use the network to get a string;
return "hello " + name; // Use your immagination.
}
}
An AsyncTask defined as public so that it can be re-used easily.
public class GetFooTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground( String... name ) {
return MyStaticClass.getFoo(name[0]);
}
}
Now to use it. Your static library or public async task could not have known what you need to do with the resulting string. So you tell it what to do with the result here:
public class MyActivity extends Activity {
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_view);
// You've already defined how to get the data
// so using it requires only minimal code now.
GetFooTask titleTask = new GetFooTask() {
#Override
public void onPostExecute( String heading ) {
((TextView) findViewById(R.id.heading)).setText(heading);
}
};
titleTask.execute("John");
}
}
In this example you can use the GetFooTask in as many activities as you like, just tell it where to put the data each time.
If you really think you will never want to do two network tasks on the same thread then you can combine the static code and the "abstract" AsyncTask. But more often than not I find I want to fire several things to and from the network before I finally return a result. If I did the threading in the network static code I would end up firing 10 threads for one request... therefore I keep threading out the static code.

using handler for every single task(method) in android

Hello i am new to android and android thread so want to know that
How could we use more number of thread in order to perform every single task or method so that while user click on any UI component it does effect the performance ,having little knowledge of how the handler thread and asynctask work.But how can we run every method inside the asynctask so to do the operation and mean while user can do the other operation also.
In the application
i have voice recording from mic.
next showing progress bar.
next showing gallery with some image and with that setting effect to the picture.
The recommended way is to use AsyncTasks for long running tasks. So, not everything needs to be run with AsyncTasks, as you can get a performance hit due to the context switching.
As for how AsyncTasks work, read the documentation.
Use an AsyncTask and make sure to implement these as needed. You mention the idea of doing something in the background while a user is doing something so I'm guessing you'll want to alter the UI.
Take a look at these links for an more details from Android. They cover Runnable, AsyncTask and Handler
Overview of them all http://developer.android.com/guide/components/processes-and-threads.html
AsyncTask example http://developer.android.com/reference/android/os/AsyncTask.html
Old but relevant, Painless Threading http://android-developers.blogspot.com/2009/05/painless-threading.html
Another, more complex example http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I don't generally paste full examples in here but I had a lot of trouble finding an example I was happy with for a long time and to help you and others, here is my preferred method. I generally use an AsyncTask with a callback to the Activity that started the task.
In this example, I'm pretending that a user has triggered onClick(...) such as with a button, but could be anything that triggers a call into the Activity.
// Within your Activity, call a custom AsyncTask such as MyTask
public class MyActivity extends Activity implements View.OnClickListener, MyTask.OnTaskComplete {
//...
public void onClick(View v) {
// For example, thet user clicked a button
// get data via your task
// using `this` will tell the MyTask object to use this Activty
// for the listener
MyTask task = new MyTask(this);
task.execute(); // data returned in callback below
}
public void onTaskComplete(MyObject obj) {
// After the AsyncTask completes, it calls this callback.
// use your data here
mTextBox.setText(obj.getName);
}
}
Getting the data out of a task can be done many ways, but I prefer an interface such as OnTaskComplete that is implemented above and triggered below.
The main idea here is that I often want to keep away from inner classes as they become more complex. Mostly a personal preference, but it allows me to separate reusable tasks outside of one class.
public class MyTask extends AsyncTask<Void, Void, MyObject> {
public static interface OnTaskComplete {
public abstract void onTaskComplete(MyObject obj);
}
static final String TAG = "MyTask";
private OnTaskComplete mListener;
public MyTask(OnTaskComplete listener) {
Log.d(TAG, "new MyTask");
if (listener == null)
throw new NullPointerException("Listener may not be null");
this.mListener = listener;
}
#Override
protected MyObject doInBackground(Void... unused) {
Log.d(TAG, "doInBackground");
// do background tasks
MyObbject obj = new MyObject();
// Do long running tasks here to not block the UI
obj.populateData();
return
}
#Override
protected void onPostExecute(MyObject obj) {
Log.d(TAG, "onPostExecute");
this.mListener.onTaskComplete(obj);
}
}

Generic asyncTask with callback (for web services)

I've already developed many Android apps that make web service requests, always with the following approach:
In every activity that need to make a web service request, I define an inner AsyncTask that shows a ProgressDialog in onPreExecute(), makes the web service call in doInBackground, and dismisses the progressDialog and updates the results in the UI from onPostExecute().
My concern is: Is there a better (shorter) way to do it? Does it make sense to repeat all that code in every activity? I've been googling a lot, but I've found nothing.
My question is: Couldn't I define a Callback interface? for example this one:
public interface RequestCallback {
public void onSuccess(Whatever whatever);
public void onError(ErrorCode errorCode, String message);
}
... and then define an external class, for example AsyncRequest, that wraps the AsyncTask definition and the ProgressDialog show() and dismiss() statements. So, all activities would just need to instantiate that class, and pass in the following parameters:
1) The method of the web service to run
2) A Bundle with all the parameters of that method of the web service
3) A RequestCallback instance (that could be an anonymous inline instance, where I could update the UI from onSuccess())
4) The context of the Activity (necessary to show the ProgressDialog(), so I would still need a way to prevent configuration change exceptions and so...),
Do you find this a good design? It could save hundreds of lines of code...
Your approach is what I did on my project. And it saved a lot of code as you said, I don't have any complaint about it. But here is some issues that I want to tell you:
You should create new instance of AsyncTask every time you do a background thread to avoid to pile callback.
For the progress dialog, I use it as Singleton, because you don't show many dialogs at the same time. The dialog will be showed when you call the background job, and will be dismiss in the callback. Here is what I did:
private void showProgressDialog(String strMess){
if(null == progressDialog){
progressDialog = new ProgressDialog(MainActivity.this);
}
if(!progressDialog.isShowing()){
progressDialog.setMessage(strMess);
progressDialog.show();
}
}
private void hideProgressDialog(){
if(null != progressDialog && progressDialog.isShowing()){
progressDialog.dismiss();
}
}
void someMethod(){
showProgressDialog("Loading...");
doBackgroundJob(param, new RequestCallBack() {
public void onRequestCompleted(String message, boolean isSuccess) {
hideProgressDialog();
if(isSuccess){
}else{
//do something on error
}
}
});
}
It is an optional, I defined an interface to notify instead of specific class, for each response I use one class, so in base class, I don't care what the response is. Here is it:
public interface OnRequestCompleted<TResponse> {
void requestCompleted(TResponse response);
}
public abstract class BaseRequest<TResponse> implements IRequest{
protected OnRequestCompleted<TResponse> delegate;
protected Class<TResponse> responseClass;
#Override
public void send() {
new HttpTask().execute();
}
private class HttpTask extends AsyncTask<Void, Void, String> {
//...
#Override
protected void onPostExecute(String result) {
if (null != response && null != delegate) {
delegate.requestCompleted(response);
}
}
}
// the response example
public class GroupResponse {
public static class Clip {
public int clipId;
public String detail;
}
public static class Movie {
public int movieId;
public String detail;
}
}
In the subclass of BaseRequest, I will tell it exactly what the response class is (Movie, Clip...)
Hope this help.
If you use it already and it works for you, then yes it makes sense to make it generic and save the time (and bugs) of reimplementing the same thing dozens of times. If you ever find yourself copy-pasting large sections of code with few to no differences you should turn it into a library function or class of some sort. Otherwise if you find a problem later you'll have to fix it in a dozen places. It doesn't even matter if you think of a better way to do things later- its still easier to change it in one place than a dozen.
The only real issue I'd have with your solution is I wouldn't add the progress bar to it- I'd handle it in the calling code and the onSuccess/onError implementations. That way you could also reuse it for a background call that doesn't need to put up a UI. I try to keep my UI decisions as far away from data grabbing code as possible, MVC patterns are good.

Use Asynctask as a private class or with broadcast receiver?

I'm trying to make an application that uses Asynctask. Particularly, I want to make different http petitions with different JSON in different activities without the activity being frozen while the communication is done.
At first I thought to use asynctask as a private inner class in those activities, but I saw that they share a lot of code. So I thought to make a single class and play with broadcast receivers as I need to monitorize when I receive the result of the http petition, and isn't good to interfere with activity directly in the onPostExecute while in a different class.
What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.
Excuse my poor english, if needed I'll try to specify more clearly.
Thanks in advance
Background
What I want to know is, what is more efficient and better practice. Make a class that has the shared code and extends asynctask, then doing inner classes for each activity that extends that one or make a single asynctask that sends broadcast and receive them with each activity when needed.
I'm unclear as to why these are your only two options. Create a single AsyncTask, such as JsonPetitionTask, then push a new JsonPetitionTask.Data object. This object would contain your URL, your JSON, and any other data you need.
Setting up the AsyncTask
Something like this:
public class JsonPetitionTask extends AsyncTask<JsonPetitionTask.Data, Integer, Boolean> {
protected Boolean doInBackground(JsonPetitionTask.Data... args) {
for (int i = 0; i < args.length; i++) {
JsonPetitionTask.Data data = args[i];
// Send your JSON; check for errors, and return false if needed.
if (isCancelled()) break;
}
return true;
}
protected void onProgressUpdate(Integer... progress) {
// Show progress?
}
protected void onPostExecute(Boolean result) {
// result is your success true/false.
}
public static class Data {
public String jsonContent;
public String petitionUrl;
public Data(String content, String url) {
jsonContent = content;
petitionUrl = url;
}
}
}
Calling the JsonPetitionTask
Then you can call it like so:
JsonPetitionTask.Data data = new JsonPetitionTask.Data(myJSON, myURL);
new JsonPetitionTask().execute(data);
And voilĂ , you've executed your AsyncTask using only one class with no receivers.
Implementing a callback
Now, if you want to register a callback (something to execute that is specific to the calling code), that's a bit trickier. If this is part of what you're looking for, I'll be glad to edit this post and explain it.
To add a callback, we can use the Runnable class to execute some code after the job is done.
Firstly, we need to add a new field in the Data inner class:
public Runnable callback;
Next, before we call execute(), we need to add a new callback to our data object.
data.callback = new Runnable() {
public void run() {
// Whatever code you want to run on completion.
}
};
Third, in the JsonPetitionTask class, we need a list of things to run:
private ArrayList<Runnable> mRunnables = new ArrayList<Runnable>();
Make sure, in each iteration of the doInBackground() loop, that you do mRunnables.add(data.callback);.
Lastly, in onPostExecute(), we need to call this:
protected void onPostExecute(Boolean result) {
for (Runnable r : mRunnables)
if (r != null) r.run();
}
I do realize I didn't send result to the Runnable, however I didn't feel like implementing a new Runnable type just to handle that. If you need this, I guess that's a bit of homework for you!
The way I found the best is just simply create public class that extends AsyncTask and then you just override onPostExecute function in every activity you use it.
Example:
MyDataTask dataTask = new MyDataTask() //you can add your parameters in class constructor
{
#Override
protected void onPostExecute(Object result) //replace Object with your result type
{
MyActivity.this.doStuff(result); //use result in current activity
}
};
you can also create some custom functions to set private variables in datatask
dataTask.AddParam("user", username);
dataTask.AddParam("pass", pass);
and then just execute it with your args...
dataTask.execute(myArgs);
I have used Async task class as single class. And for every Webservice call i have used unique IntentFilter to Broadcast response.
Put that Broadcast receiver in every class. You have perfect solution.
Its working well.

Categories

Resources