'Android: Alternatives to AsyncTask?
for my app I made a framework for all network calls to an external API. I put everything in "Services" like: UserService
, MessageService
etc. So now when I want to call a network method I can't do this in the UI-Thread of my Activity
so I made an AsyncTask
and everything was just fine =)
But now I want something like giving the method to execute to the AsyncTask
so I don't need to write an AsyncTask
for every method of my network-framework. So instead of having something like this:
public class NetworkTask extends AsyncTask<UserService, Void, Void> {
@Override
protected Void doInBackground(UserService... params) {
UserService userService = params[0];
userService.getUser();
return null;
}
}
I want something more "abstract" so the AsyncTask
doesn't need to know the "getUser" method? But I can't find any idea of how to do this... Maybe the AsyncTask is not good for this anyway?
Solution 1:[1]
There are plenty AsyncTask alternatives :
and plus Needle - Multithreading library for Android
Solution 2:[2]
Maybe you can use a third party library like Retrofit If you work with images I strongly suggest picasso
Solution 3:[3]
Remember that Android has a limit of threads and AsyncTasks.
You can use 2 libraries to do the same work of AsyncTasks:
Volley -> http://www.androidhive.info/2014/05/android-working-with-volley-library-1/
LoopJ -> http://loopj.com/android-async-http/
Update:
I really recommend Retrofit 2. http://square.github.io/retrofit/
Solution 4:[4]
RxJAVA is best option
Alternative to Asynctask for Web service call,file upload,file download is Android Fast Networking Lib
For other case you can use following method
Disposable d = Observable.fromCallable(new Callable<HashMap<String, String>>() {
@Override
public HashMap<String, String> call() throws Exception {
// will run in background thread (same as doinBackground)
return postParam;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<HashMap<String, String>>() {
@Override
public void accept(final HashMap<String, String> data) throws Exception {
// will run in UI thread. write down code for on PostExecute
}
});
// write down code for on preExecute
DisposableManager.add(d);
// dispose object
@Override
protected void onDestroy() {
super.onDestroy();
DisposableManager.dispose();
}
// Dispose manager class
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
public class DisposableManager {
private static CompositeDisposable compositeDisposable;
public static void add(Disposable disposable) {
getCompositeDisposable().add(disposable);
}
public static void dispose() {
getCompositeDisposable().dispose();
}
private static CompositeDisposable getCompositeDisposable() {
if (compositeDisposable == null || compositeDisposable.isDisposed()) {
compositeDisposable = new CompositeDisposable();
}
return compositeDisposable;
}
private DisposableManager() {}
}
Solution 5:[5]
If you dont prefer third party libraries and prefer library with simplicity and good documentation and support, Loaders is the best choice.
For our delight, AsyncTaskLoader(subclass of Loaders) performs the same function as the AsyncTask, but better and also can handle Activity configuration changes more easily.And best thing is it behaves within the life cycles of Fragments and Activities.
For more information and subclasses please check this documentation.
Solution 6:[6]
Loaders should be used instead of directly using Async tasks. There are specific Loader API's for specific operations like perform transations in sqlite database etc.
Solution 7:[7]
I have post for this there are multiple solutions for this to replace asynctask like using
- Executors Service
- RxJava
- Listenable Futures
- Courotines using Kotlin
here is my Implementations
Solution 8:[8]
Using Kotlin and Coroutines it is pretty simple to implement it by yourself:
fun <P, R> CoroutineScope.executeAsyncTask(
onPreExecute: () -> Unit,
doInBackground: suspend (suspend (P) -> Unit) -> R,
onPostExecute: (R) -> Unit,
onProgressUpdate: (P) -> Unit
) = launch {
onPreExecute()
val result = withContext(Dispatchers.IO) {
doInBackground {
withContext(Dispatchers.Main) { onProgressUpdate(it) }
}
}
onPostExecute(result)
}
executeAsyncTask
is an extension function on CoroutineScope
. Having any CoroutineScope
instance with Dispatchers.Main
context, for example viewModelScope
we can call this function like the following:
viewModelScope.executeAsyncTask(
onPreExecute = {
// ... runs in Main Thread
}, doInBackground = { publishProgress: suspend (progress: Int) -> Unit ->
// ... runs in Background Thread
// simulate progress update
publishProgress(50) // call `publishProgress` to update progress, `onProgressUpdate` will be called
delay(1000)
publishProgress(100)
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// runs in Main Thread
// ... here "it" is a data returned from "doInBackground"
}, onProgressUpdate = {
// runs in Main Thread
// ... here "it" contains progress
}
)
The main condition is that the CoroutineScope
should have Dispatchers.Main
context. viewModelScope
has it by default.
Solution 9:[9]
You can use Volley library which does it work on the background thread and gives you control back to main thread when things are done.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow