android async task - android

I have a app I'm making with an AsyncTask. The result of the task needs to be assigned to a variable in the base app class. I currently have:
protected void onPostExecute(int[][]... end) {
MainVar=end[0];
}
but this doesn't transfer the data. I'm guessing I'm going about this wrong, but I wasn't sure how to do it reading the docs, so how should this be done?

It's generally right what you tried. You're given the result of the type int[][] in onPostExecute(). But don't use primitive types. AsyncTask Extensions are generic and need three types: AsyncTask<Params, Progress, Result>
which may be Void or anything else (but no primitive data type). Hope that helps!

Related

Google Play services Task API: continueWith vs continueWithTask

This is about Task.
What's the difference between task.continueWith() and task.continueWithTask(), can you provide an example for each one?
The primary difference between continueWith and continueWithTask is one of the generic types of the Continuation you pass to it.
You can think of a Continuation as something that converts some input type to some output type. If you define a Continuation<IN, OUT>, where IN is the input type passed to its then method via a Task<IN>, and OUT is the type that method returns.
When calling continueWith, you pass a Continuation<IN, OUT>, and the then method is expected to compute and return the OUT value given a Task<IN> value as input. You might choose to do this if you don't have any blocking work to do for the conversion, such as reducing an integer array to the sum of its elements or counting the number of words in a String.
When calling continueWithTask, you pass a Continuation<IN, Task<OUT>>, and the then method is expected to return a Task<OUT> that eventually generates the OUT value, given the IN value as input. You might choose this if you are able to delegate the conversion work to an existing reusable Task.
Practically speaking, you aren't required to choose one or the other to do your work. It's a matter of preferred style, or if you have a nice Task ready to delegate your conversation rather than a Continuation. Typically you only use a Continuations if you have a pipeline of conversions to chain together.
The javadoc links here show some examples of Continuations. Also, to learn more, you can read about them in part three of my blog series. To be fair, continueWithTask is the only part of the Task API I don't directly discuss anywhere in that series, mostly because conceptually it doesn't differ very much from continueWith.
Just to add to what Doug said, I would put it like this:
continueWith will wrap the result of the then method in a Task. continueWithTask will not; it expects the then method to return a Task, and thus avoids the double wrapping of a task within a task.
continueWithTask is perfect when you want to use a Continuation and a TaskCompletionSource together.
I'd like to add, that continueWith and continueWithTask really got me into trouble, obviously because I did not truly understand the API, but also did the naming confuse me. Maybe an example of my failure can prevent others from doing the same.
tl;dr
When to use which method:
Use continueWith if you want to use the result of the previous task and return a new result within your Continuation's then method. And you need to hand it over to some other continuation or use it afterwards in listeners. The return value of continueWith is a Task that just WRAPS your return value of the then method.
Use continueWithTask if you want to use the result of the previous task,
and somewhat use it in a new task, that you create within your Continuation's then method. The return value of continueWithTask is a task that YOU create inside of then and has an own generic result.
Do NOT return a task in your continuation's then and use it with continueWith. It might compile and execute for years without a warning, but also without doing it's job.
IF you directly append a listener after continueWith, this listener
will give you a task THAT ONLY WRAPS the result of your then return
value. If this return value is a task itself, do not expect it to be
executed(!!!).
Long story!
I had a calling chain like this:
private Task<SomeResult> getTask() {
PreloadingTask.create().continueWith(additionalTask()).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
source.setResult(someResult);
} else {
source.setException(new Exception());
}
});
return source.getTask();
}
So as you can see, additionalTask() must return some sort of Continuation<IN, OUT>, that implements the method then as
#Override
public OUT then(Task<IN> task){ ... }};
In my case I did not need to check for OUT, because I just wanted to do some additional computations AFTER the PreloadingTask was done and forwards it's result to my additionalTask() continuation.
I wanted to execute the task from additionalTask(), and afterwards the onCompleteListener should have been called.
private Continuation<PreviousResult, Task<Void>> additionalTask() {
return task -> {
PreviousResult r = task.getResult();
simpleResultModification(r);
return new AdditionalTask(r);
);
};
}
What happend? The onCompleteListener was called directly, because my then method got executed and returned it's result, which was an instance of AdditionalTask.
This AdditionalTask then got wrapped into another task and handed over for the onCompleteListener as the result.
And my AdditionalTask got never executed.
That's why you should use continueWithTask if you return a task, within then.
There's a big difference between continueWith() and continueWithTask() related to task cancellation.
More info here - Task API docs.
continueWith() : If the previous Task is canceled, the returned Task will also be canceled and the Continuation would not execute.
continueWithTask() : If the previous Task is canceled, the Continuation would still execute and task.isCanceled() is true can be observed in the Continuation.

What is the purpose of adding parameters to an AsyncTask?

Sorry for being a newbie, I've looked everywhere and I just don't get it.
Asynctask needs 3 parameters; e.g.
but what is the point of these parameters?
I am trying to run a geocoder in a separate thread and I have this
private class GetCurrentCity extends AsyncTask<String, Void, Void>{
but I literally made those parameters up. I have no idea what I'm supposed to put there. I don't need a progress bar or anything to be transferred to the other thread except for the line of code that is already in doInBackground() . Then I need a string to be returned from that, and I am using onPostExecute(String returnedAddress) for that.
I am confused. Help please!
From the doc of AsyncTask
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }
Rather than an API reference, here's a little more description. First, many people will use an AsyncTask inline as an anonymous class; keep that in mind. It looks like you've extended it with your own class (which is totally fine), but it likely means you're passing the necessary data in the constructor and referencing it as class variables. In that case, some of the arguments won't make as much sense.
So picture an anonymous inline class of AsyncTask. The first thing it's going to do is run some processing in the background. To do that, you need a way to pass data to the doInBackground method (because you don't have a constructor to call and pass it data). So the first argument is the type of data you're going to pass to it. If you don't have to pass anything, use Void, or use Object, or anything at all, really, because it has to be part of the method signature but you'd ignore it anyway.
For many situations, one will want to provide progress updates. For example, you might use the Float type to represent percent complete, or Long to represent bytes read from a file, or String for general messages to a user. You use the progress type to pass out interim progress information (think of uploading a file to facebook or downloading a file, where it updates the notification status with the progress - this is where/how you'd do that). You've said you don't care about it in your case, so use Void and don't bother implementing any progress methods.
Finally, when the task completes, you need to get to the result in the onPostExecute. So your doInBackground will return a value (of this type) and the AsyncTask framework will pass it to onPostExecute. Again, this makes more sense for an anonymous class with no further body. If you'd hold any results in a class member, that's fine also (but unnecessary). If you don't need to do anything on complete, or don't need to pass any data, use Void (and return null from doInBackground). I find it's useful at the least to return a Boolean for "completed successfully or failed," so you have that information (which might influence whether you post a success or failure notification, as notification of task complete is a common onPostExecute operation).
Hope some more explanation with examples helps.
Those are for when you want to pass something to it at time of execution or passing between runInBackground and onPostExecute. You can simply make all three Void in class declaration.
AsyncTask | Android Developers
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the
background computation.
Result, the type of the result of the background computation.
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
private class MyTask extends AsyncTask<Void, Void, Void> { ... }

new AsyncTask<ObjectA, ObjectB, ObjectC>, what goes where?

regarding AsyncTask<ObjectA, ObjectB, ObjectC> parameters, I am always confused about which Object effects what.
One effects my doInBackGround return type, one effects my doInBackGround input type, and the third object effects something else.
When I am changing what kind of things I want to send in and return, this gets very confusing.
What does ObjectA effect
What does ObjectB effect
What does ObjectC effect
(ignore possible misuse of effect/affect)
From the documentation:
ObjectA - doInBackground();
ObjectB - progress indicator: publishProgress(), etc
ObjectC - onPostExecute(), what doInBackground() must return
To actually quote:
AsyncTask's generic types
The three types used by an asynchronous task are the following:
1.Params, the type of the parameters sent to the task upon execution.
2.Progress, the type of the progress units published during the background computation.
3.Result, the type of the result of the background computation.
Not all types are always used by an asynchronous task. To mark a type
as unused, simply use the type Void:
private class MyTask extends AsyncTask<Params, Progress, Result> { ... }
Please read the documentation before asking such kind of questions: http://developer.android.com/reference/android/os/AsyncTask.html
It says:
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution.
Progress, the type of the progress units published during the background computation.
Result, the type of the result of the background computation.
Not all types are always used by an asynchronous task. To mark a type
as unused, simply use the type Void.

How to let Asynctask update UI in different ways

This is a problem that I keep running into often with using Asyntask. The way to contact the UI thread is to call publishProgress() & this method accepts an array of only one TYPE of parameter.
A thread running in the background doing complicated computations might need to update the UI at different points using different types of object.
Let me illustrate with an example:
...do some processing...
// Send UI thread the integer values of the width & height of the image
...do some more processing...
// Send UI thread a String with custom message.
...do some more processing...
// Send UI thread an instance of MyObject so it can extract & display certain values
...do some cleanup job & finish...
However, onProgressUpdate() accepts an array of only one type.
So do I make that an all encompassing Object type? How do I know how to downcast it since this method can be called from line 1, 2 or 3 so which time is it?
Surely there must be a good way to achieve this?
EDIT: What I'd really love to see, if it were possible in Android, would be some way of defining publishProgress1(user-defined args1), publishProgress2(user-defined args2), publishProgress3(user-defined args3) ...
In your 3rd case...
// Send UI thread an instance of MyObject
...there's an argument to say you would do this in onPostExecute() although that depends on what you meant from your illustration.
You could easily do as you suggest in passing an all encompassing object. The object could have various fields (integer, string, object) plus an 'action' to take describing which of those fields are valid and need to be processed.
You could simply pass an int enum such as PROCESS_INT_WIDTH_AND_HEIGHT, PROCESS_STRING_MESSAGE, PROCESS_OBJECT etc. There's nothing to stop you doing this...
private static class MyAsyncTask extends AsyncTask<String, int, Void> {
private int width;
private int height;
private String customMessage;
private MyObject myObject;
#Override
protected Void doInBackground(String... params) {
width = 10;
height = 10;
publishProgress(PROCESS_INT_WIDTH_AND_HEIGHT);
}
protected void onProgressUpdate(int... progress) {
if (progress == PROCESS_INT_WIDTH_AND_HEIGHT)
// Process width and height
}
}
In other words, the onProgressUpdate() method simply responds to a 'command' and processes the relevant private fields accordingly.
If you want to stick with AsyncTask, another option is use a different class at different times, and test the type with instanceof.
However, this sounds like a relatively complex task, so I'd suggest looking at using Handler and posting it [Runnable]s2 from a regular Thread, or using runOnUiThread.
You might also want to read Painless Threading
Hope this helps,
Phil Lello
I don't think there is any other way of doing this. Create a base class with a getType method and then use this as your type for appropriate casting.
Would a generic type work in this scenario? You could typecast the values as needed. Example AsyncTask prototype:
new AsyncTask<String, Object, List<?>>(){
...
I also recall reading that AsyncTask is most suited only for short tasks. Consider the other thread models for complex and long-running operations.
If the values you're returning have a corresponding state in the AsyncTask processing, you could create a private member inside the AsyncTask for each datum/type you need, then assign an integer to each state and in onProgressUpdate(Integer...) put a switch(state) that does the job based on the int state it gets from publishProgress(state).
(this might not be the clearest answer I gave)

Need help with AsyncTasks - Android Application

Hey, I have an application which logs onto a few sites using defaulthttpclient and I've found I'm going to need to use the AsyncTask as the requests hold up the UI thread. In my code, I create an instance of a state class i.e. State state = new O2State(); with different states for different sites.
I then call state.logon(String username, String password); which returns a string containing details of the result so:
String result = state.logon(username, password);
I've been trying to implement asynctasks to run this code in another thread and return the string back to the UI thread on completion. The idea is I will display a progress dialog, run the thread, and on complete, will display a dialog with the result.
I've been looking at this example:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Where I'm stuck is:
I don't think I'll need any arguments, but doinbackground seems to require a list of parameters. I'm also unfamiliar with this time of method argument declaration.
Secondly:
I'm not sure how to return the resulting string when the thread is finished executing. Should I just create a "DoThisWhenTheThreadIsFinished(String result)" and call this from onPostExecute?
Anyway, I hope this isn't too confusing to read and I'd really appreciate any help you can offer.
Thanks
Where you don't need parameters just specify the type (e.g. String) and ignore it, or you could use the Void class (note the capital V).
What you suggest for how to return control back to the UI thread to reflect the update is a good approach. i.e. in onPostExecute() call a method on the activity to update the UI.
As a general rule if any operations will take more than a couple of hundred milliseconds, use a separate thread. You may also want to use a rotating progress indicator to show the app is doing something.
(when people answer your questions, always rate the ones you like, and pick one as the "best" answer. you get points doing this, and it helps others later).

Categories

Resources