AsyncTask in Android 4.0

Showing 1-48 of 48 messages
AsyncTask in Android 4.0 Nathan 4/20/12 12:16 PM
Still adjusting to the changes in Android 4.0 regarding AsyncTask.

If I understand right, the default behavior of execute is changing to one single thread pool with only one thread? With the reason cited that programmers are not capable of handling a bigger threadpool (I'm paraphrasing).

Does that mean, that absent some code changes, all asynctasks inside a process will only happen sequentially? 

So therefore, if I have a service running DownloadDictionaryTask in the background, and the user chooses a menu item that starts CheckDiskSpaceTask, the progress bar will cycle without any progress because the task never makes progress?

A user and I could briefly reproduce a situation where, as far as I could tell, no asynctasks were running, yet my AsyncTask would not even start. In this case, I couldn't even get one thread. Alas, I cannot reproduce that situation, which appeared to fix itself without any code changes.

But in any case, this isn't really acceptable to have only one asynctask task run at once. But there is no central way to control that behavior, is there? I would have to replace 83 instances of task.execute with task.executeonExecutor. Since the above method is only available in SDK>11, this isn't a one line change - it's more like 10-20 lines of code with reflection, and some extensive testing.

In my opinion, this a deplorable punishment for those developers who have dutifully followed the AsyncTask pattern, which, to this day, the Android platform has encouraged.

Or perhaps I am reading this wrong. Maybe all DownloadDictionaryTasks share one pool, and all CheckDiskSpaceTasks share another pool. In that case, the rule is that only one task *of the same concrete type* can run at once. This rule, I can probably live with, as I've used my own threading pools for tasks that are truly data parallel. 

Can anyone enlighten me more?

Nathan

Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/20/12 12:29 PM
On Fri, Apr 20, 2012 at 3:16 PM, Nathan <nathan....@gmail.com> wrote:
> If I understand right, the default behavior of execute is changing to one
> single thread pool with only one thread?

I have not been able to confirm that this change is in place. When I
try testing a bunch of tasks, they seem to execute in parallel, even
on 4.0.3 (haven't tried 4.0.4 yet).

> Does that mean, that absent some code changes, all asynctasks inside a
> process will only happen sequentially?

Once this change takes effect (if it has not already), then yes.

> So therefore, if I have a service running DownloadDictionaryTask in the
> background, and the user chooses a menu item that starts CheckDiskSpaceTask,
> the progress bar will cycle without any progress because the task never
> makes progress?

Yes. Either use the supplied pooled executor with executeOnExecutor(),
or move one of those things out of AsyncTask (e.g.,
DownloadDictionaryTask might be better as an IntentService, if it is
supposed to keep rolling even if the user leaves the app).

> A user and I could briefly reproduce a situation where, as far as I could
> tell, no asynctasks were running, yet my AsyncTask would not even start. In
> this case, I couldn't even get one thread. Alas, I cannot reproduce that
> situation, which appeared to fix itself without any code changes.

If you come up with a reproducible scenario that demonstrates that the
default executor is the single-threaded one, I'd be interested in
taking a peek at it.

> But in any case, this isn't really acceptable to have only one asynctask
> task run at once. But there is no central way to control that behavior, is
> there? I would have to replace 83 instances of task.execute with
> task.executeonExecutor. Since the above method is only available in SDK>11,
> this isn't a one line change - it's more like 10-20 lines of code with
> reflection, and some extensive testing.

You wouldn't necessarily need to use reflection. Set your build target
to 11+ and create your own static execute() method somewhere that,
based on API level, uses execute() or executeOnExecutor() directly.
It's a code change, though, regardless.

Another possibility would be for you to grab an older AsyncTask out of
github.com/android, refactor it into your own package, and change your
import statements to use it instead of the stock AsyncTask.

> In my opinion, this a deplorable punishment for those developers who have
> dutifully followed the AsyncTask pattern, which, to this day, the Android
> platform has encouraged.

You certainly won't get any argument from me on this. My gast was most
certainly flabbered when Romain Guy mentioned this possibility a
year-plus ago.

> Or perhaps I am reading this wrong. Maybe all DownloadDictionaryTasks share
> one pool, and all CheckDiskSpaceTasks share another pool.

The pool is static at the AsyncTask level. Hence, all subclasses share
a single pool, unless I'm seriously missing something.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!

Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 12:31 PM
The default, starting with 4.0, is to use the serial executor:


But there is also an way to explicitly use the thread pool executor:


i.e.:

new MyAsyncTask(....).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ....);

Or you could supply your own executor parameter that's constructed outside of AsyncTask.

The predefined thread pool executor "constant" is new with API 11 (Android 3.0).

-- K

20 апреля 2012 г. 23:16 пользователь Nathan <nathan....@gmail.com> написал:


Nathan

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 12:55 PM
20 апреля 2012 г. 23:29 пользователь Mark Murphy <mmu...@commonsware.com> написал:

On Fri, Apr 20, 2012 at 3:16 PM, Nathan <nathan....@gmail.com> wrote:
> If I understand right, the default behavior of execute is changing to one
> single thread pool with only one thread?

I have not been able to confirm that this change is in place. When I
try testing a bunch of tasks, they seem to execute in parallel, even
on 4.0.3 (haven't tried 4.0.4 yet).


The default is definitely serial on my GNex with 4.0.2.

Did they revert it again for the 4.0.3 that you have?

-- K

Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/20/12 1:21 PM
2012/4/20 Kostya Vasilyev <kman...@gmail.com>:

> The default is definitely serial on my GNex with 4.0.2.
>
> Did they revert it again for the 4.0.3 that you have?

Here's how I am testing it (sloppy code, but it meets the need):

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

public class ParallelTasksActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new SillyTask().execute("A");
    new SillyTask().execute("B");
    new SillyTask().execute("C");
    new SillyTask().execute("D");
    new SillyTask().execute("E");
  }

  class SillyTask extends AsyncTask<String, String, Void> {
    @Override
    protected Void doInBackground(String... params) {
      for (int i=0; i < 5; i++) {
        String msg=params[0] + String.valueOf(i);

        Log.d("ParallelTasks", msg);
        SystemClock.sleep(1000);
      }

      return(null);
    }
  }
}

Now, if AsyncTask executes serially, I would expect:

A0
A1
A2
A3
A4
B0
B1
B2
B3
B4
...

Even if the letters were out of order (e.g., C before A), the
numerical index would be in order, because the task would be tying up
the one-and-only thread, so there should be no interleaving between
letter.

Yet, when I run this on 4.0.3 or 4.0.4, I get:

04-20 20:15:34.574: D/ParallelTasks(2965): D0
04-20 20:15:34.574: D/ParallelTasks(2965): C0
04-20 20:15:34.574: D/ParallelTasks(2965): E0
04-20 20:15:34.582: D/ParallelTasks(2965): A0
04-20 20:15:34.586: D/ParallelTasks(2965): B0
04-20 20:15:35.574: D/ParallelTasks(2965): D1
04-20 20:15:35.574: D/ParallelTasks(2965): E1
04-20 20:15:35.574: D/ParallelTasks(2965): C1
04-20 20:15:35.582: D/ParallelTasks(2965): A1
04-20 20:15:35.586: D/ParallelTasks(2965): B1
04-20 20:15:36.578: D/ParallelTasks(2965): E2
04-20 20:15:36.578: D/ParallelTasks(2965): C2
04-20 20:15:36.586: D/ParallelTasks(2965): D2
04-20 20:15:36.586: D/ParallelTasks(2965): A2
04-20 20:15:36.589: D/ParallelTasks(2965): B2
04-20 20:15:37.586: D/ParallelTasks(2965): C3
04-20 20:15:37.593: D/ParallelTasks(2965): D3
04-20 20:15:37.593: D/ParallelTasks(2965): B3
04-20 20:15:37.593: D/ParallelTasks(2965): E3
04-20 20:15:37.593: D/ParallelTasks(2965): A3
04-20 20:15:38.589: D/ParallelTasks(2965): C4
04-20 20:15:38.601: D/ParallelTasks(2965): D4
04-20 20:15:38.601: D/ParallelTasks(2965): E4
04-20 20:15:38.605: D/ParallelTasks(2965): B4
04-20 20:15:38.609: D/ParallelTasks(2965): A4

Since the five AsyncTask instances are interleaving their results, I
have to assume that they are running in parallel.

Even if I change doInBackground() to:

    @Override
    protected Void doInBackground(String... params) {
        Log.d("ParallelTasks", params[0] + " started");
        SystemClock.sleep(10000);
        Log.d("ParallelTasks", params[0] + " ended");

      return(null);
    }

so there's a 10-second tie-up, I get:

04-20 20:20:02.886: D/ParallelTasks(3044): D started
04-20 20:20:02.898: D/ParallelTasks(3044): B started
04-20 20:20:02.898: D/ParallelTasks(3044): A started
04-20 20:20:02.898: D/ParallelTasks(3044): E started
04-20 20:20:02.898: D/ParallelTasks(3044): C started
04-20 20:20:12.898: D/ParallelTasks(3044): A ended
04-20 20:20:12.902: D/ParallelTasks(3044): C ended
04-20 20:20:12.910: D/ParallelTasks(3044): D ended
04-20 20:20:12.914: D/ParallelTasks(3044): B ended
04-20 20:20:12.918: D/ParallelTasks(3044): E ended

All five start, 10 seconds elapses, and all five end, indicating that
they are running in parallel.

Where I am going wrong in my analysis?

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!

Re: [android-developers] AsyncTask in Android 4.0 Nathan 4/20/12 1:26 PM


On Friday, April 20, 2012 12:29:24 PM UTC-7, Mark Murphy (a Commons Guy) wrote:
On Fri, Apr 20, 2012 at 3:16 PM, Nathan  wrote:
> If I understand right, the default behavior of execute is changing to one
> single thread pool with only one thread?

I have not been able to confirm that this change is in place. When I
try testing a bunch of tasks, they seem to execute in parallel, even
on 4.0.3 (haven't tried 4.0.4 yet).

I don't download the source myself, but if this source listing is accurate, it must be fully in place.

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java
 

Yes. Either use the supplied pooled executor with executeOnExecutor(),
or move one of those things out of AsyncTask (e.g.,
DownloadDictionaryTask might be better as an IntentService, if it is
supposed to keep rolling even if the user leaves the app).

I sure hope they won't be messing with the threadpool for intentservices too. 
 
Nathan
Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/20/12 1:34 PM
On Fri, Apr 20, 2012 at 4:26 PM, Nathan <nathan....@gmail.com> wrote:
> I don't download the source myself, but if this source listing is accurate,
> it must be fully in place.
>
> https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java

I've seen that, which is why I can't explain what I'm seeing at runtime.

> I sure hope they won't be messing with the threadpool for intentservices
> too.

IntentService does not have a thread pool. IntentService has always
had just one thread. Now, if you have several IntentServices in an
app, they will all have independent threads.

--

Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!

Re: [android-developers] AsyncTask in Android 4.0 Nathan 4/20/12 1:36 PM


On Friday, April 20, 2012 12:31:01 PM UTC-7, Kostya Vasilyev wrote:
The default, starting with 4.0, is to use the serial executor:


But there is also an way to explicitly use the thread pool executor:


i.e.:

new MyAsyncTask(....).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ....);

It's not quite so easy for a project that wants to run on pre 3.0 platforms. If you have an elegant solution for that, it will save me some time.

Nathan
Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 1:44 PM


21 апреля 2012 г. 0:36 пользователь Nathan <nathan....@gmail.com> написал:


It's not quite so easy for a project that wants to run on pre 3.0 platforms. If you have an elegant solution for that, it will save me some time.

Idea 1: Write a wrapper method in a utility class somewhere... replace direct calls to execute with the one line call to this method

Idea 2: Use Mark's suggestion grab AsyncTask sources and embed it in your own app so you'll have control over this.

Idea 3: Don't use AsyncTask... but then you'll need a replacement, and it's probably easiest to use idea 2 rather than starting from scratch.

-- K
 

Nathan

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 2:13 PM
Curiouser and curiouser!” Cried Alice

Running your code on my GNex with official 4.0.2 I get this:

04-21 00:41:08.327 I/ParallelTasks(14355): A started
04-21 00:41:18.335 I/ParallelTasks(14355): A ended
04-21 00:41:18.335 I/ParallelTasks(14355): B started
04-21 00:41:28.335 I/ParallelTasks(14355): B ended
04-21 00:41:28.335 I/ParallelTasks(14355): C started
04-21 00:41:38.343 I/ParallelTasks(14355): C ended
04-21 00:41:38.343 I/ParallelTasks(14355): D started
04-21 00:41:48.335 I/ParallelTasks(14355): D ended
04-21 00:41:48.343 I/ParallelTasks(14355): E started
04-21 00:41:58.343 I/ParallelTasks(14355): E ended

Note the timestamps.

Here is my test, same idea really:


and it also shows that the default execute() on my GNex with 4.0.2 is serialized:

04-21 00:51:22.788 I/TestAsyncTask(14899): testDefaultExecutor
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 0
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 1
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 2
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 3
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 4
04-21 00:51:22.788 I/TestAsyncTask(14899): doInBackground 0
04-21 00:51:27.796 I/TestAsyncTask(14899): doInBackground 1
04-21 00:51:32.796 I/TestAsyncTask(14899): doInBackground 2
04-21 00:51:37.796 I/TestAsyncTask(14899): doInBackground 3
04-21 00:51:42.804 I/TestAsyncTask(14899): doInBackground 4
04-21 00:51:47.804 I/TestAsyncTask(14899): done

04-21 00:51:47.804 I/TestAsyncTask(14899): testThreadPoolExecutor
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 0
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 1
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 2
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 3
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 4
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 0
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 2
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 1
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 3
04-21 00:51:47.811 I/TestAsyncTask(14899): doInBackground 4
04-21 00:51:52.811 I/TestAsyncTask(14899): done

Again, note the timestamps (although the order is obvious).

On an Asus Tranformer with 4.0.3, I am getting the same results, the default execute is serial.

Sanity check on a Sony Tablet S with 3.2.1, the default execute uses a thread pool:

04-21 01:10:22.870 I/TestAsyncTask( 1002): testDefaultExecutor
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 0
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 1
04-21 01:10:22.880 I/TestAsyncTask( 1002): doInBackground 0
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 2
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 3
04-21 01:10:22.890 I/TestAsyncTask( 1002): onPreExecute 4
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 4
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 3
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 2
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 1
04-21 01:10:27.890 I/TestAsyncTask( 1002): done

04-21 01:10:27.890 I/TestAsyncTask( 1002): testThreadPoolExecutor
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 0
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 1
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 2
04-21 01:10:27.900 I/TestAsyncTask( 1002): onPreExecute 3
04-21 01:10:27.900 I/TestAsyncTask( 1002): onPreExecute 4
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 0
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 1
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 3
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 4
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 2
04-21 01:10:32.900 I/TestAsyncTask( 1002): done

04-21 01:10:32.900 I/ParallelTasks( 1002): A started
04-21 01:10:32.900 I/ParallelTasks( 1002): B started
04-21 01:10:32.910 I/ParallelTasks( 1002): D started
04-21 01:10:32.910 I/ParallelTasks( 1002): E started
04-21 01:10:32.910 I/ParallelTasks( 1002): C started
04-21 01:10:42.910 I/ParallelTasks( 1002): B ended
04-21 01:10:42.910 I/ParallelTasks( 1002): C ended
04-21 01:10:42.910 I/ParallelTasks( 1002): A ended
04-21 01:10:42.910 I/ParallelTasks( 1002): E ended
04-21 01:10:42.910 I/ParallelTasks( 1002): D ended


-- K

21 апреля 2012 г. 0:21 пользователь Mark Murphy <mmu...@commonsware.com> написал:

2012/4/20 Kostya Vasilyev <kman...@gmail.com>:
> The default is definitely serial on my GNex with 4.0.2.
>
> Did they revert it again for the 4.0.3 that you have?

Here's how I am testing it (sloppy code, but it meets the need):

Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/20/12 2:24 PM
Yes if your targetSdkVersion is >= 12, then as of that release the default executor is serial.

This change was made because we realized we had a lot of bugs in the platform itself where async tasks where created that had implicit ordering dependences, so with the default parallel execution there were subtle rare bugs that would result.

I can't address how much smarter you are than the rest of us, but I am pretty convinced that for the vast majority of us the best thing to do is have the default here be safe, allowing developers to change it for the specific cases where they don't want that behavior.

This is a lesson I seem to learn every few years: multithreading is hard.  Once you think you now understand it and are an expert, you are heading soon to another painful lesson that multithreading is hard.

Having an API to set the default executor back to parallel is not a solution, because it just gives you an easy way to create the exact same problems we are trying to fix.  For example, if you have an async task that executes due to some user input to update some data, there is a very very good chance that if you allow these to be parallel you will have a bug.

Even with something as simple as a check box (which is one of the real cases that drove this change) you can have this problem.  If you run an executor to save to disk the new state of the check box, there *are* situations where if you tap long enough and the CPU is loaded in the right way, you will end up with the first state being saved after the second.

So, yes, the default is serial, and you must explicitly decide when to use a parellel executor.  You should only use a parallel executor when you know this is what you want and it is safe: when it is something that can take a significant amount of time, and you know has no dependencies with any other background tasks you may execute.  So in your example here, the solution is to run your download task with AsyncTask.THREAD_POOL_EXECUTOR and leave the others with the default serial executor.



Nathan

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en



--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/20/12 2:31 PM
On Fri, Apr 20, 2012 at 5:24 PM, Dianne Hackborn <hac...@android.com> wrote:
> Yes if your targetSdkVersion is >= 12, then as of that release the default
> executor is serial.

Bingo! It's the targetSdkVersion that's controlling the behavior.
Looking at the AsyncTask source code, I can't quite see how that's
happening, but at least I can confirm the results.

Though for me, the serialized behavior does not kick in until a
targetSdkVersion of 13 -- 12 still gives me parallel operation.

Thanks for the clarification!

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!

Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/20/12 2:39 PM
Sorry yes it is API 13, I turned around the logic of the code when I glanced at it:

        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
        // implementation to use the pool executor.  Normally, we use the
        // serialized executor as the default. This has to happen in the
        // main thread so the main looper is set right.
        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }



--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-d...@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 3:08 PM
Perhaps the documentation needs to be updated?

As of right now, it says:

"Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. "

... and makes no mention of the target sdk setting in the manifest.

Still, an app with targetSdkVersion 14 or 15 running on a 3.* device will still be getting a pool of threads.

-- K

21 апреля 2012 г. 1:39 пользователь Dianne Hackborn <hac...@android.com> написал:

Re: [android-developers] AsyncTask in Android 4.0 b0b 4/20/12 3:26 PM


On Friday, 20 April 2012 23:24:34 UTC+2, Dianne Hackborn wrote:
Yes if your targetSdkVersion is >= 12, then as of that release the default executor is serial.

This change was made because we realized we had a lot of bugs in the platform itself where async tasks where created that had implicit ordering dependences, so with the default parallel execution there were subtle rare bugs that would result.

While I understand why this change why made it introduced some subtle bugs in apps running on ICS with the SerialExecutor vs the the Threaded Executor.
It is unfortunate and I'm not sure it was a wise decision to change such an important behaviour that late.

Notably, lots of app uses AsyncTask to do networking I/O for which you can spend quite a lot of time in doInBackground() for example if the connection timeout or is
very slow. This is not uncommon on mobile networks.
Consider such an AsyncTask blocked for several seconds (maybe 20s or 30s) in doInBackground(). With the serial executor it blocks *all pending* AsyncTask in the queue until it finishes.
So it can give to the user the app is frozen or that something that should happening or be updated isn't. That's a new kind of ANR without an actual ANR.

To summarize, all apps who used AsyncTask assuming parallel execution are possibly broken if doInBackground() does not finishes quick.
When I explained this to a well know Google engineer, I was told : "You fool! thou shall use AsyncTask only for short lived task! Use your own AsyncTask replacement for long-running parallel tasks".  Don't get even me started on the scientific definition of "short lived task"...

In the end since I knew why I need the ThreadDed executor, I just wrapped all my AsyncTask execution with this function:

static public <T> void executeAsyncTask(AsyncTask<T,?,?> task, T... params) {
        if(isHoneycombOrLater()) {
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        } else {
            task.execute(params);
        }
    }

Conclusion: there's probably man apps broken in subtle ways on ICS because of this change.









Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/20/12 3:39 PM
On Fri, Apr 20, 2012 at 6:26 PM, b0b <pujos....@gmail.com> wrote:
> Conclusion: there's probably man apps broken in subtle ways on ICS because
> of this change.

Probably not, only because they have to explicitly set the
targetSdkVersion to 13+, and I don't know how many people are setting
it that high.

That being said, it's a fairly significant change for something as
subtle as slightly increasing the targetSdkVersion, which is why we
need to make sure everyone knows about this. I agree with Kostya's
comment regarding docs -- at this point, I think an Android Developers
Blog post is probably needed.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!

Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/20/12 3:41 PM
2012/4/20 Kostya Vasilyev <kman...@gmail.com>
Perhaps the documentation needs to be updated?

Yes sorry it wasn't updated in ICS, I have it updated in the current dev tree.

Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/20/12 3:42 PM
On Fri, Apr 20, 2012 at 3:26 PM, b0b <pujos....@gmail.com> wrote:
While I understand why this change why made it introduced some subtle bugs in apps running on ICS with the SerialExecutor vs the the Threaded Executor.
It is unfortunate and I'm not sure it was a wise decision to change such an important behaviour that late.

We were very careful to not change the behavior for any existing apps.  It only changes once you update your app and explicitly set your targetSdkVersion to indicate you are compatible with the version of Android where the change occurred.  This is standard practice we use frequently when making changes to the platform that impact behavior applications may be relying on.

Re: [android-developers] AsyncTask in Android 4.0 b0b 4/20/12 3:45 PM
To complete on this topic, I think it would be very useful to post an article on this issue on the developer's blog,
asking developers whose app run on APi 13+ to review all their AsyncTask execute() code to check
if it can use the default Executor or if it must use the Threaded Executor, for example in the case of doing networking I/O or other possibly time consuming tasks.

Re: [android-developers] AsyncTask in Android 4.0 Nathan 4/20/12 3:49 PM


On Friday, April 20, 2012 3:26:26 PM UTC-7, b0b wrote:


On Friday, 20 April 2012 23:24:34 UTC+2, Dianne Hackborn wrote:
Yes if your targetSdkVersion is >= 12, then as of that release the default executor is serial.

This change was made because we realized we had a lot of bugs in the platform itself where async tasks where created that had implicit ordering dependences, so with the default parallel execution there were subtle rare bugs that would result.

While I understand why this change why made it introduced some subtle bugs in apps running on ICS with the SerialExecutor vs the the Threaded Executor.
It is unfortunate and I'm not sure it was a wise decision to change such an important behaviour that late.

Notably, lots of app uses AsyncTask to do networking I/O for which you can spend quite a lot of time in doInBackground() for example if the connection timeout or is
very slow. This is not uncommon on mobile networks.
Consider such an AsyncTask blocked for several seconds (maybe 20s or 30s) in doInBackground(). With the serial executor it blocks *all pending* AsyncTask in the queue until it finishes.
So it can give to the user the app is frozen or that something that should happening or be updated isn't. That's a new kind of ANR without an actual ANR.

To summarize, all apps who used AsyncTask assuming parallel execution are possibly broken if doInBackground() does not finishes quick.
When I explained this to a well know Google engineer, I was told : "You fool! thou shall use AsyncTask only for short lived task! Use your own AsyncTask replacement for long-running parallel tasks".  Don't get even me started on the scientific definition of "short lived task"...


B0b's concerns echo my own.

If you don't use an AsyncTask, you'll get an ANR. But if you do, you have a progress bar that never moves because something else is running, and the users will think it is frozen.

Nowhere have I been told that AsyncTasks were only for short lived tasks (like a few seconds). I have used it for longer tasks. And I've never really assumed that it was safe to use it for task with dependencies between them.

If the platform is using the AsyncTask internally, it better be short lived tasks.

Nonetheless, I can't disagree with Diane's lesson that multithreading is hard. But the other thing I've learned about threads is that I always seem to need more of them.  

Nathan

 
Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 3:50 PM


21 апреля 2012 г. 2:39 пользователь Mark Murphy <mmu...@commonsware.com> написал:

On Fri, Apr 20, 2012 at 6:26 PM, b0b <pujos....@gmail.com> wrote:
> Conclusion: there's probably man apps broken in subtle ways on ICS because
> of this change.

Probably not, only because they have to explicitly set the
targetSdkVersion to 13+, and I don't know how many people are setting
it that high.

I do for one of my apps :)

But then I don't use AsyncTask at all.

The thread pool thing seemed unrealiable to me back in the 2.* days...

Besides, my threading logic is typically either too simple for AsyncTask, or too complex :)

-- K
 

That being said, it's a fairly significant change for something as
subtle as slightly increasing the targetSdkVersion, which is why we
need to make sure everyone knows about this. I agree with Kostya's
comment regarding docs -- at this point, I think an Android Developers
Blog post is probably needed.
Re: [android-developers] AsyncTask in Android 4.0 b0b 4/20/12 3:52 PM

> Conclusion: there's probably man apps broken in subtle ways on ICS because
> of this change.

Probably not, only because they have to explicitly set the
targetSdkVersion to 13+, and I don't know how many people are setting
it that high.


Bumping targetSdkVersion to the latest version is something very common and generally harmless.
Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 4:04 PM


21.04.2012 2:52 пользователь "b0b" <pujos....@gmail.com> написал:

Not sure I agree.

There are some subtle activity lifecycle callback changes starting with 3.0, some not so subtle home screen widget changes starting with 4.0... just what comes to mind right away...

Re: [android-developers] AsyncTask in Android 4.0 b0b 4/20/12 4:07 PM
To illustrate this further, consider this code from Tim Bray downlading images in a ListView. Something that must be implemented in thousand apps:

http://android-developers.blogspot.fr/2010/07/multithreading-for-performance.html

This code running unmodified on ICS will download images sequencially (instead of in parallel) and any timeouting download will block all other downloads.

The fix  is just a matter of changing the Executor, but it illustrates nicely the side effect of the change.




Re: [android-developers] AsyncTask in Android 4.0 Romain Guy 4/20/12 4:07 PM
> There are some subtle activity lifecycle callback changes starting with 3.0,
> some not so subtle home screen widget changes starting with 4.0... just what
> comes to mind right away...

And don't forget hardware acceleration that gets turned on when targetSdk=14+

--
Romain Guy
Android framework engineer
roma...@android.com

Re: [android-developers] AsyncTask in Android 4.0 Kostya Vasilyev 4/20/12 4:24 PM


21.04.2012 3:09 пользователь "Romain Guy" <roma...@android.com> написал:
>
> > There are some subtle activity lifecycle callback changes starting with 3.0,
> > some not so subtle home screen widget changes starting with 4.0... just what
> > comes to mind right away...
>
> And don't forget hardware acceleration that gets turned on when targetSdk=14+

Ah, yes, thank you.

... Which affects not only graphics intensive apps, but simple view based ones as well. Just an example: I remember having to fix Dianne's old fast scroller before I could reuse it with hw accel on.

So, changing the targetSdk may break code in various ways and requires careful (re)testing.

>
> --
> Romain Guy
> Android framework engineer
> roma...@android.com
>
> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-d...@googlegroups.com
> To unsubscribe from this group, send email to
> android-developers+unsubscribe@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en

Re: AsyncTask in Android 4.0 FiltrSoft 4/20/12 5:57 PM
Some of this is a little over my head, but from what I can understand, if the targetSdkVersion is set to 13 or greater and I have a "long running" AsyncTask (not exactly sure what is considered a long running task), I should use this code to execute the AsyncTask?

       if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
           task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
       } else {
           task.execute(params);
       }

Does in matter if the AsyncTask is used in a service or not?

-Kris

http://www.filtrsoft.com - Custom news monitoring apps
Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/20/12 6:24 PM
2012/4/20 Kostya Vasilyev <kman...@gmail.com>

So, changing the targetSdk may break code in various ways and requires careful (re)testing.


Yes, the whole reason for targetSdkVersion is to allow the platform to turn off various compatibility behavior for older applications.  If you bump up your SDK version, you are saying you have fully tested your app against that SDK version so are not relying on any of the older compatibility behavior.

You can see many many things listed here that are impacted by SDK version:


Actually there are a number more that aren't spelled out so well in the current public doc (but are usually documented at the APIs that are impacted).  I also recently in our development tree went through and tried to get in the documentation in VERSION_CODES everything that is impacted by targetSdkVersion.

--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

Re: [android-developers] AsyncTask in Android 4.0 Nadeem Hasan 4/20/12 7:29 PM
My app targets sdk 15 (tested on CM9) and uses AsyncTask in every activity but only one at a time. Explains why I did not notice the change. I agree that this change deserves better documentation in the API reference in addition to a blog post.
Re: AsyncTask in Android 4.0 MichaelEGR 4/20/12 8:38 PM
On Apr 20, 12:16 pm, Nathan <nathan.d.mel...@gmail.com> wrote:
> In my opinion, this a deplorable punishment for those developers who have
> dutifully followed the AsyncTask pattern, which, to this day, the Android
> platform has encouraged.

Add it to the list... ;)   I can't exactly call the unfurling Android
SDK responsible API development. Quick and efficient if one judges
efficiency by market share. Yes yes everyone works hard on the Android
team, so do we your end users. When I saw AsyncTask pop up in 1.5 I
thought to myself why oh why is there such a lightweight abstraction
being offered over the already fine and dandy Executor framework as
AsyncTask doesn't exactly add all too much. Granted I already had a
nice abstraction layer on top of the Executor framework carried over
from the desktop, so AsyncTask seemed quite moot and as we now see a
bit destructive in terms of default behavior when one is trying to
target the larger ecosystem. Also I don't have the time to go back and
check 1.5 sources for this conversation, but I'd be really curious to
see if the original AsyncTask didn't use the Executor framework
underneath; that would be telling.

I actually planned on discussing this as 1 of 5 main topics for my
AnDevCon class coming up next month ("Java performance tricks for the
troubles"); this certainly classifies as a big trouble (more so than I
thought with the change in default behavior for AsyncTask) and now
it's definitely in the class. I'll present my abstraction over the
Executor framework; it's of course component oriented and can easily
be extended. The one thing that cracks me up is that with not a whole
lot of work one can still use a single ThreadPoolExecutor and
simultaneously submit tasks to be run in a single queue manner or all
tasks at once up to the pool limit. I also have a long running pending
Executor submitter system component that is very handy for the GUI
checkbox example a previous poster mentioned that saves state each
press of the checkbox. In that particular submitter if a current task
is running the latest task is stored as pending, each successive press
of the checkbox (or any GUI element) replaces the pending task while
one is executing. Instead of queuing up 30 tasks to run with 30
presses of the checkbox if a user rapidly presses the checkbox and
there is a long running task kicked off just the first and last
presses get tasks submitted.

So basically the advice I'm offering is to copy / modify AsyncTask as
necessary in ones own package or ditch usage of AsyncTask entirely and
adopt a solid existing framework that won't change or simply
investigate the Executor framework directly and build your own
abstraction. It's the only foolproof way to get reliable task
execution across all versions of Android and it is pointless / very
bad style to embed conditional logic based on API level to limp along
using AsyncTask. I know the Android team is just trying to provide a
helper functionality, but to change the default behavior like this is
yet another API sin; IMHO

This revelation in the change of default behavior really demands an
Android Dev blog post and the clearest possible documentation to be
posted.
Re: AsyncTask in Android 4.0 William Ferguson 4/20/12 8:39 PM
The real problem that is see with this change is that while you can modify all of your own uses of AsyncTask to suit you can be entirely hamstrung by one or more 3rd-party libraries that are also using AsyncTasks.

Personally I've been using my own replication of AsyncTask for the last 12 months as it avoided changes of threading behaviour between sdk versions. But even good 3rd party libraries can cut down down due to changes in policy like this.

William


On Saturday, April 21, 2012 5:16:35 AM UTC+10, Nathan wrote:
Still adjusting to the changes in Android 4.0 regarding AsyncTask.

If I understand right, the default behavior of execute is changing to one single thread pool with only one thread? With the reason cited that programmers are not capable of handling a bigger threadpool (I'm paraphrasing).

Does that mean, that absent some code changes, all asynctasks inside a process will only happen sequentially? 

So therefore, if I have a service running DownloadDictionaryTask in the background, and the user chooses a menu item that starts CheckDiskSpaceTask, the progress bar will cycle without any progress because the task never makes progress?

A user and I could briefly reproduce a situation where, as far as I could tell, no asynctasks were running, yet my AsyncTask would not even start. In this case, I couldn't even get one thread. Alas, I cannot reproduce that situation, which appeared to fix itself without any code changes.

But in any case, this isn't really acceptable to have only one asynctask task run at once. But there is no central way to control that behavior, is there? I would have to replace 83 instances of task.execute with task.executeonExecutor. Since the above method is only available in SDK>11, this isn't a one line change - it's more like 10-20 lines of code with reflection, and some extensive testing.

In my opinion, this a deplorable punishment for those developers who have dutifully followed the AsyncTask pattern, which, to this day, the Android platform has encouraged.

Or perhaps I am reading this wrong. Maybe all DownloadDictionaryTasks share one pool, and all CheckDiskSpaceTasks share another pool. In that case, the rule is that only one task *of the same concrete type* can run at once. This rule, I can probably live with, as I've used my own threading pools for tasks that are truly data parallel. 

Can anyone enlighten me more?

Nathan

Re: AsyncTask in Android 4.0 b0b 4/21/12 3:18 AM


On Saturday, 21 April 2012 05:39:30 UTC+2, William Ferguson wrote:
The real problem that is see with this change is that while you can modify all of your own uses of AsyncTask to suit you can be entirely hamstrung by one or more 3rd-party libraries that are also using AsyncTasks.


This concern could have been addressed with  a single line of code, if this private API had been made public:

AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

But in infinite wisdom, it was decided that developers would use (or abuse) above API wrong and thus this API was made private.
So instead of a single line change, if you want the Threaded Executor for all your AsyncTasks you have to find and modify all your execute() calls.


Re: [android-developers] Re: AsyncTask in Android 4.0 Romain Guy 4/21/12 3:58 PM
> I know the Android team is just trying to provide a
> helper functionality, but to change the default behavior like this is
> yet another API sin; IMHO

FWIW the parallel/serialized behavior was not initially documented, on
purpose. The sole role of AsyncTask was to help not block the UI
thread, not offer a fully fledged threading framework since, as you
mentioned, the core APIs provide solid foundations for that. The
advice I regularly give developers is to use the executor framework
directly if they want more control over their tasks.

And to answer your question, AsyncTask was already using the executor
framework in 1.5. Speaking of 1.5, AsyncTask was using a serialized
behavior in that release. This behavior is explained in the current
documentation of the execute() method:

"Note: this function schedules the task on a queue for a single
background thread or pool of threads depending on the platform
version. When first introduced, AsyncTasks were executed serially on a
single background thread. Starting with DONUT, this was changed to a
pool of threads allowing multiple tasks to operate in parallel. After
HONEYCOMB, it is planned to change this back to a single thread to
avoid common application errors caused by parallel execution. If you
truly want parallel execution, you can use the
executeOnExecutor(Executor, Params...) version of this method with
THREAD_POOL_EXECUTOR; however, see commentary there for warnings on
its use."

--
Romain Guy
Android framework engineer
roma...@android.com

Re: [android-developers] Re: AsyncTask in Android 4.0 FiltrSoft 4/22/12 10:00 AM
I have to agree with Nathan, I've never read anywhere that AsyncTasks should only be used for "short lived" tasks (a couple seconds).  The official documenation says "This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers."  Not only is it bad grammer :), it can easily be interpreted as ok to use for most background tasks (not everyone can get direct advice from a framework engineer).  On top of that, why would AsyncTasks offer "onProgressUpdate" if they are only used for tasks that take a couple seconds?  That would indicate it's made for "long running" tasks.

Again, a lot of this is over my head, but maybe it helps to see the point of view from an "average" developer.

-Kris

http://www.filtrsoft.com
Custom news monitoring apps
Re: AsyncTask in Android 4.0 Michael 4/23/12 10:23 AM

I have concerns of making such major changes implicitly in android.
For the developers who follow this thread they are safe, what about
the thousands of developers who wont be reading this thread? Any
possibility of making such major changes compile failures or deprecate
old api and create new api with forced selection of parallel/serial
executor.

Easier to fix failures at app compile time for all developers, not so
easy for each developer who is depending on current parallel asynctask
behavior to google search for related asynctask slowness problems and
find the cause of this six months down the road when 3.0+ is the
default android on majority of devices?
Re: [android-developers] AsyncTask in Android 4.0 RichardC 4/24/12 1:18 AM
Will this change break CursorLoader in multi-fragment Activities?

If I have an Activity with 2 Fragements, each fragment using a CursorLoader to load its own data. CursorLoader is derived from AsyncTaskLoader which uses AsyncTask to do the work which includes monitoring for data changes therefore the AsyncTask (in the Loader) cannot finish until the activity is closed.  How can the 2nd CursorLoader run if the 1st never finishes?

--
RichardC


On Friday, April 20, 2012 10:24:34 PM UTC+1, Dianne Hackborn wrote:
Yes if your targetSdkVersion is >= 12, then as of that release the default executor is serial.

This change was made because we realized we had a lot of bugs in the platform itself where async tasks where created that had implicit ordering dependences, so with the default parallel execution there were subtle rare bugs that would result.

I can't address how much smarter you are than the rest of us, but I am pretty convinced that for the vast majority of us the best thing to do is have the default here be safe, allowing developers to change it for the specific cases where they don't want that behavior.

This is a lesson I seem to learn every few years: multithreading is hard.  Once you think you now understand it and are an expert, you are heading soon to another painful lesson that multithreading is hard.

Having an API to set the default executor back to parallel is not a solution, because it just gives you an easy way to create the exact same problems we are trying to fix.  For example, if you have an async task that executes due to some user input to update some data, there is a very very good chance that if you allow these to be parallel you will have a bug.

Even with something as simple as a check box (which is one of the real cases that drove this change) you can have this problem.  If you run an executor to save to disk the new state of the check box, there *are* situations where if you tap long enough and the CPU is loaded in the right way, you will end up with the first state being saved after the second.

So, yes, the default is serial, and you must explicitly decide when to use a parellel executor.  You should only use a parallel executor when you know this is what you want and it is safe: when it is something that can take a significant amount of time, and you know has no dependencies with any other background tasks you may execute.  So in your example here, the solution is to run your download task with AsyncTask.THREAD_POOL_EXECUTOR and leave the others with the default serial executor.


Re: [android-developers] AsyncTask in Android 4.0 Mark Murphy 4/24/12 4:01 AM
On Tue, Apr 24, 2012 at 4:18 AM, RichardC
<richard...@googlemail.com> wrote:
> Will this change break CursorLoader in multi-fragment Activities?

CursorLoader uses the THREAD_POOL_EXECUTOR, last I checked.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_Android Programming Tutorials_ Version 4.1 Available!

Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 4/24/12 5:32 PM
On Tue, Apr 24, 2012 at 1:18 AM, RichardC <richard...@googlemail.com> wrote:
Will this change break CursorLoader in multi-fragment Activities?

No.

--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support, and so won't reply to such e-mails.  All such questions should be posted on public forums, where I and others can see and answer them.

Re: AsyncTask in Android 4.0 Emanuele Ricci 5/16/12 3:14 AM
Hi Michael do you have some good alternative to the current AsyncTask implementation?

Anyway the real big big big problem is for the 3rd party library or SDK that my project is currently used.
I'm using some ads SDK and I'm pretty sure that they are using also AsyncTask in the "normal" way so I'm really afraid that their asynctasks will block mine for the "serial problem" we were discussing.
Re: [android-developers] AsyncTask in Android 4.0 Dirk Jäckel 5/16/12 8:17 AM
On Saturday, April 21, 2012 12:52:17 AM UTC+2, b0b wrote:

> Conclusion: there's probably man apps broken in subtle ways on ICS because
> of this change.

Probably not, only because they have to explicitly set the
targetSdkVersion to 13+, and I don't know how many people are setting
it that high.


Bumping targetSdkVersion to the latest version is something very common and generally harmless.

And recommended by developer relations advocates.
 
Re: [android-developers] AsyncTask in Android 4.0 Dirk Jäckel 5/16/12 9:09 AM
On Friday, April 20, 2012 11:39:51 PM UTC+2, Dianne Hackborn wrote:
Sorry yes it is API 13, I turned around the logic of the code when I glanced at it:

        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
        // implementation to use the pool executor.  Normally, we use the
        // serialized executor as the default. This has to happen in the
        // main thread so the main looper is set right.


Please document this here: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html#HONEYCOMB_MR2

Or is there a better place for developers to stay informed what a targetSDKVersion change means for their app?

Regards,
Dirk

 
Re: [android-developers] AsyncTask in Android 4.0 Dianne Hackborn 5/16/12 9:19 AM
On Wed, May 16, 2012 at 9:09 AM, Dirk Jäckel <dirk.j...@gmail.com> wrote:
Or is there a better place for developers to stay informed what a targetSDKVersion change means for their app?

As I already said, there are currently a number of things missing from that, but I updated those a bit ago and that should appear in the next API release.

Jerry Stralko 5/17/12 11:13 AM <This message has been deleted.>
Re: AsyncTask in Android 4.0 Jerry Stralko 5/17/12 11:36 AM


On Friday, April 20, 2012 3:16:35 PM UTC-4, Nathan wrote:
Still adjusting to the changes in Android 4.0 regarding AsyncTask.

If I understand right, the default behavior of execute is changing to one single thread pool with only one thread? With the reason cited that programmers are not capable of handling a bigger threadpool (I'm paraphrasing).

 
I'm also trying to figuring out why setDefaultExecutor is hide but public?

    /** @hide */
    public static void setDefaultExecutor(Executor exec) {
        sDefaultExecutor = exec;
    }

Is this because it is subject to change and non-framework clients (i.e. third party dev) should be use this? For my app I wanted to globally change the Executor to ThreadPool, but that doesn't seem possible. 

So what I'm currently doing is subclass the AsyncTask like so:

public abstract class ThreadPoolAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {

/*

* This is a helper method to allow ICS AsyncTask to run in a thread pool, 

* without break API compatability with pre-ICS devices.

* If you don't want a threadpool use the default AsyncTask since that is the 

* default for ICS.  If you don't want a threadpool for pre-ICS (API level < 13) 

* then you need to wrote your own AsyncTask. Use the AsyncTask.java as a good starting point.

*/

public void executeOnThreadPool(Params...params) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

this.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);

} else {

this.execute(params);

}

}

}


I'm just wondering is this is a good solution?  This way I can use ThreadPoolAsyncTask for task that can run in parallel and don't have any implicit dependence on other tasks. And use AsyncTask directly if i want them to run in serial.

Thanks,
Re: AsyncTask in Android 4.0 npike 6/11/12 8:32 AM
How about AsyncTaskLoader?  Are they effected by this change?  (Will
loaders not run in parallel if the SDK level is set to 13+?)

If so, any work arounds to restore previous behavior?



On Apr 20, 4:07 pm, Romain Guy <romain...@android.com> wrote:
> > There are some subtle activity lifecycle callback changes starting with 3.0,
> > some not so subtle home screen widget changes starting with 4.0... just what
> > comes to mind right away...
>
> And don't forget hardware acceleration that gets turned on when targetSdk=14+
>
> --
> Romain Guy
> Android framework engineer
> romain...@android.com
Re: [android-developers] Re: AsyncTask in Android 4.0 Mark Murphy 6/12/12 2:47 AM
On Mon, Jun 11, 2012 at 11:32 AM, npike <mav...@gmail.com> wrote:
> How about AsyncTaskLoader?  Are they effected by this change?  (Will
> loaders not run in parallel if the SDK level is set to 13+?)

AsyncTaskLoader specifically opts into the thread pool executor and so
will work in parallel.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!
Re: AsyncTask in Android 4.0 tom 10/10/12 3:44 AM
I like this change. And have used a custom AsyncTask taken from API10 with the following changes for awhile now.

   private static final int CORE_POOL_SIZE = 1;

    private static final int MAXIMUM_POOL_SIZE = 1;


ps. hope this is the correct way to get the serial execution on API<11.


Nicolas Gramlich 5/11/13 1:18 PM <This message has been deleted.>
More topics »