2

I have 4 async tasks which load data from internet. In same time I show activity with animation, when tasks complete I need to start another activty with loaded data.

My async methods on Kotlin (same as async tasks written on java)

private fun getArtistData(name: String) {
    val getArtistDataAsync = object : AsyncTask<String, Void, Artist>() {

        override fun doInBackground(vararg args: String?): Artist? {
            Log.i(TAG, "Получаем данные в AsyncTask для $mArtistName")
            Caller.getInstance().cache = null
            return Artist.getInfo(args[0], "26cc2ebf6da38bc646733f661bfc6268");
        }

        override fun onPostExecute(result: Artist?) {
            super.onPostExecute(result)
            Log.i(TAG, "Возвращаем данные из AsyncTask для $mArtistName")
            CommonUtilities.artistInstance = result as Artist;
        }
    }

    val getTopTracksAsync = object : AsyncTask<String,Void,ArrayList<Track>>(){
        override fun doInBackground(vararg args: String?): ArrayList<Track>? {
            Log.i(TAG, "Получаем список песен в AsyncTask для $mArtistName")
            Caller.getInstance().cache = null
            return Artist.getTopTracks(args[0], "26cc2ebf6da38bc646733f661bfc6268") as ArrayList<Track>;
        }

        override fun onPostExecute(result: ArrayList<Track>?) {
            super.onPostExecute(result)
            Log.i(TAG, "Возвращаем список песен из AsyncTask для $mArtistName")
            CommonUtilities.trackListInstance = result;
        }
    }

    val getSimilarBandsAsync = object : AsyncTask<String,Void,ArrayList<Artist>>(){
        override fun doInBackground(vararg args: String?): ArrayList<Artist>? {
            Log.i(TAG, "Получаем список похожих групп в AsyncTask для $mArtistName")
            Caller.getInstance().cache = null
            return Artist.getSimilar(args[0], "26cc2ebf6da38bc646733f661bfc6268") as ArrayList<Artist>?
        }

        override fun onPostExecute(result: ArrayList<Artist>?) {
            super.onPostExecute(result)
            Log.i(TAG, "Возвращаем список похожих групп из AsyncTask для $mArtistName")
            CommonUtilities.artistListInstance = result;
        }
    }

    val getTopAlbumsAsync = object : AsyncTask<String,Void, ArrayList<Album>>(){
        override fun doInBackground(vararg p0: String?): ArrayList<Album>? {
            Log.i(TAG, "Получаем список альбомов в AsyncTask для $mArtistName")
            Caller.getInstance().cache = null
            return Artist.getTopAlbums(p0[0],"26cc2ebf6da38bc646733f661bfc6268") as ArrayList<Album>?;
        }

        override fun onPostExecute(result: ArrayList<Album>?) {
            super.onPostExecute(result)
            Log.i(TAG, "Возвращаем список альбомов из AsyncTask для $mArtistName")
            CommonUtilities.albumListInstance = result;
        }
    }

I trying to invoke my methods here:

val runAllTasks = object : AsyncTask<Void,Void,Void>(){
        override fun doInBackground(vararg p0: Void?): Void? {
            getArtistDataAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, name)
            getSimilarBandsAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, name)
            getTopTracksAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, name)
            getTopAlbumsAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, name)
            return null
        }

        override fun onPostExecute(result: Void?) {
            super.onPostExecute(result)

            startActivity(Intent(applicationContext, DetailsActivity::class.java))
        }
    }

    runAllTasks.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Damon Shine
  • 33
  • 2
  • 6
  • The Kotlin library Kovenant has a very easy model for this, by using promises (simply `task { ... }`) and then combining them allows you to create a compound promise that can then continue when some or all complete. http://kovenant.komponents.nl/ ... and it supports Android out of the box, only needing a special small addon if you want automatic callbacks on the UI thread. http://kovenant.komponents.nl/addons/ui/ – Jayson Minard Feb 17 '16 at 19:08
  • Whatever answer is in stack overflow for Java doing the same, will work for Kotlin. Therefore this question is a dupe if you aren't looking for something like a Kotlin library to replace the async tasks. http://stackoverflow.com/questions/17418194/multiple-callback-waiting-in-android-java and http://stackoverflow.com/questions/25608795/android-how-to-detect-when-multiple-http-requests-complete and http://stackoverflow.com/questions/16504352/running-multiple-services-at-one-time-in-android ... and others – Jayson Minard Feb 17 '16 at 19:11
  • more with this tag: http://stackoverflow.com/questions/tagged/android-asynctask – Jayson Minard Feb 17 '16 at 19:13
  • You can also just have them all in a list of the resulting `AsyncTask` objects and loop it calling `get()`, it'll pause on any not done and when it passes through them all, they all must be done. – Jayson Minard Feb 17 '16 at 19:15

2 Answers2

3

I would use the Kovenant library instead, it has support on Android, is tiny, and makes this type of thing very easy using all(), combine() or and().

Kovenant is a Promise library for Kotlin. And if you are moving to Kotlin it is a good chance to checkout things that make life easier. For callbacks on the UI thread, you can use the UI Module.

Then no matter if on Android or back-end JVM programming you can use the same library, the same semantics, and have an easier programming model.

Jayson Minard
  • 84,842
  • 38
  • 184
  • 227
1

You can call a synchronized common method which count the number of asyncTask that already finished. Something like this:

private static final int NUMBER_ASYNCTASK = 4;
private static int counter = 0;

public static synchronized void asyncTaskCompleted() {
   counter++; 
    if(counter == NUMBER_ASYNCTASK)
       //start new activity
}
cherif
  • 1,164
  • 1
  • 11
  • 16
  • It also doesn't indicate which thread is doing the final callback work, here a random thread from the async pool continues on to the next task, or maybe is the UI thread yes? Not necessarily an error in the code, but something to consider which thread should continue onwards and which thread is actually making the call. – Jayson Minard Feb 17 '16 at 19:29
  • Maybe CountDownLatch could be used. Another answer in to similar question: stackoverflow.com/a/17418772/3679676 – Jayson Minard Feb 17 '16 at 19:35