Using Asynctask to Speed Up Android App Launch Time

using asynctask to speed up android app launch time

I can't just make your code an AsyncTask but I can give you an example and some help. This is an example of AsyncTask

public class TalkToServer extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);

}

@Override
protected String doInBackground(String... params) {
//do your work here
return something;
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// do something with data here-display it or send to mainactivity

}

All of your network stuff you will put in doInBackground() then if you need to update the UI you did that in the other methods. After finishing the network stuff you can update UI in onPostExecute().

This is how you would call the task

TalkToServer myAsync = new TalkToServer() //can add params if you have a constructor
myAsync.execute() //can pass params here for `doInBackground()` method

If it is an inner class of your MainActivity then it will have access to member variables of MainActivity. If its a separate class then you can pass context to constructor like

TalkToServer myAsync = new TalkToServer(this);

and create a constructor to accept Context and any other params you want

I strongly suggest going through the docs below and make sure you understand how it works. Maybe the biggest thing to understand when getting started is that doInBackground() doesn't run on the UI so you don't want to try and update any Views here but in the other AsyncTask methods or by passing data back to the MainActivity and update there
AsyncTask

AsyncTask, must it take such a performance penalty hit...?

You're not the only one observing this behaviour. The slowdown by factor 10 is probably a result of Android using a Linux cgroup (scheduling class) for threads of priority BACKGROUND or below. All these threads have to live with 10% CPU time altogether.

The good news is you don't have to live with the Thread priority settings from java.lang.Thread. You can assign your Thread a pthread (Linux thread) priority from the definitions in android.os.Process. There, you not only have Process.THREAD_PRIORITY_BACKGROUND, but also constants to adjust the priority a bit.

Currently, Android uses the background thread cgroup for all threads with priority THREAD_PRIORITY_BACKGROUND or worse, and THREAD_PRIORITY_BACKGROUND is 10 while THREAD_PRIORITY_DEFAULT is 0 and THREAD_PRIORITY_FOREGROUND is -2.

If you go for THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE (aka 9) your thread will be lifted out of the background cgroup with the 10% limitation, while not being important enough to interrupt your User Interface threads too often.

I believe there are background tasks which need a bit of computational power but which are at the same time not important enough to de facto block the UI (by consuming too much CPU in a separate thread) and Android currently has no obvious priority to assign to these, so in my view, this is one of the best priorities you can assign to such a task.

If you can use a HandlerThread it's easy to achieve:

ht = new HandlerThread("thread name", THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE);
ht.start();
h = new Handler(ht.getLooper());

If you want to go with AsyncTask, you can still do

protected final YourResult doInBackground(YourInputs... yis) {
Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE);
...
}

but be aware that the underlying implementation may reuse the same Thread object for different tasks, for the next AsyncTask, or whatever. It seems that Android simply resets the priority after doInBackground() returns, though.

Of course, if your UI really consumes CPU and you want more power for your task at the same time, taking it away from the UI, you can set another priority, maybe up to Process.THREAD_PRIORITY_FOREGROUND.

solution regarding slow process from AsyncTask while loading lots images from sdcard

It is slow because in fact you are still using one single thread (i.e. one AsyncTask.execute() call) download all images in sequence (i.e. loop all image download in your doInBackground() implementation). Yes, this is the way that google suggested how to use AsyncTask.

By calling several AsyncTask.execute() will probably speed you up, this gives you several thread running simultaneously and managed by underlying thread pool (before API level 11, this thread pool is non accessible). of cause, you need somehow split your download task into several piece and feed each piece into each AsyncTask.execute():

for (DownloadTask task : tasks) {
new AsyncTask.execute();
}

Check out here for more information.

Is android asynctask always so slow

From your description seems like the delay is even before your onPreExecute() fires? Is there perhaps something delaying your button processing (maybe handler?) causing this?

AsyncTasks are too slow for several simultaneous networking operations

Oke a couple of things going pretty wrong here.

  1. Do not use AsyncTasks for Networking. Use a service. In short, this is because your AsyncTask will stop, as soon as the Activity that started it will stop. This means that network requests get aborted easily and data goes lost and has to re-start again when the Activity is opened again.

  2. Do not use .get() on AsyncTasks. This makes the UI thread wait for the task to complete, making the whole AsyncTask idea kinda useless. In other words: This blocks your UI.

What you should do:

  1. Read up on using services. You can also have a look at a great opensource library called RoboSpice to help you with this.

  2. Stop using .get() on AsyncTasks, if you want to know when it is done just use a listener.

  3. Execute AsyncTasks on a threadpool ( myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); ) when possible.

AsyncTask.get() in Activity.onCreate makes it take too much time to load and sometimes it crashes

Your problem is that you're waiting synchronously on the main thread for your AsyncTask to finish:

parsejson.execute().get();

You should basically never be calling AsyncTask.get() on the main thread: it will block the thread until it finishes, which defeats the point of an AsyncTask, which is to not block the main thread.

Instead, you should do whatever you're waiting for in AsyncTask.onPostExecute.

How to get speed in AsyncTask?

You should execute the async task inside the location listener itself and move these lines out to main thread:

locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
Log.d(TAG,"READY");
Log.d(TAG,locationListener.);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsInterval, 0, locationListener);
Log.d(TAG,"DONE");
return "";

And in your listener:

public class MyLocationListener  implements LocationListener  {

private static final String TAG = "MyLocationListener ";

private MySpeedList speedList= new MySpeedList();

@Override
public void onLocationChanged(Location location) {
if (calculationsTask == null || calculationsTask.getStatus() == AsyncTask.Status.FINISHED) {
calculationsTask = new CalculationsTask()
calculationsTask.execute(location);
} else {
// buffer pending calculations here or cancel the currently running async task
}
}

...

CalculationsTask

 private class CalculationsTask extends AsyncTask<Location, Integer, Long> {
protected Long doInBackground(Location location) {
// do calculations here
return speed;
}

protected void onPostExecute(Long result) {
// this method is executed in UI thread
// display result to user
}
}

Here, you can deliver your calculations result through onPostExecute(...) method as this method is ran on the main thread. Also note that you cannot execute an async task the second time, so you have to create a new instance every time.

Also, if you want to access speedList in your async task, you can make the CalculationsTask an inner class of your MyLocationListener or just pass it as a parameter.



Related Topics



Leave a reply



Submit