Test order of AsyncTask completion with Robolectric - android

I have a set of AsyncTasks for which I want to test behavior when completed in different orders. Can I do this with generic Robolectric functionality or do I need to mock a complex asynchronous handling my background jobs?
Simplified I mean something like:
trigger functionality which start taskA and taskB
assert
complete taskA
assert
complete taskB
assert
trigger functionality which start taskA and taskB
assert
complete taskB
assert
complete taskA
assert
Thx

It's hard to test asynchronous code in unit tests. You can consider converting your AsyncTasks into RxJava code. There is a module for Android called RxAndroid. You can also read an article explaining how to Replace AsyncTask and AsyncTaskLoader with rx.Observable – RxJava Android Patterns. When you read section about testability, you can notice that with RxJava you can easily convert non-blocking request into synchronous, blocking request in the following way:
List results = getWeatherForLargeUsCapitals().toBlocking().first();
assertEquals(12, results.size());
After that, your application will use asynchronous code, but your tests will be synchronous and you will be sure that assertions will be executed when request is finished.

I'm not a fan of async tasks. As for me I would suggest to follow Piotr answer. This will make you app cleaner, maintainable and attractive.
If you decide to go with AsyncTask you should extract async task body and completion body to the methods. So in test you can call them in any order that you want. Of course it will require making these methods at least package visible which is not something I would to do. Because changing the code to convince the tests running is evil.

Related

Which one is better approach while performing multiple background tasks Kotlin Coroutines or ThreadPool?

I'm trying to implement start syncing process while app comes foreground.
I want to make multiple API call in the background thread, Which one will be better approach for this scenario Kotlin Coroutines or ThreadPool executor
I have tried with Kotlin Coroutines, but it seems like it try to execute all functions call in parallel which cause some Lag in APP initial times. is there a best approach to execute multiple functions in parallel
of course, Kotlin Coroutines, because coroutines aren't necessarily bound to any particular thread. A coroutine can start executing in one thread, suspend execution, and resume on a different thread. Coroutines aren't managed by the operating system. They're managed at the user space level by the Kotlin Runtime.
Kotlin Co-routines are the way to go.
Why? :
They are cheap.
Increases code readability.
Configuration setup is less (as compared to RxJava) for simple tasks.
try this
viewModelScope.launch{
val function1Async=async{ function1()}
val function2Async=async{function2()
function1Async.await()
function2Async.await()
}
If the alternative is to use ThreadPools, then you should use coroutines. They are built to make this easier. Also, you would save some memory since you would be sharing threads with other processes.
If what you need is a single thread that's continuously running in the background. Then maybe a thread is the way to go to ensure it's execution is not interrupted by a pending coroutine. Although an isolated single threaded dispatcher should solve this problem (if you have it).
You mentioned experiencing lag? Was this lag averted when you used a threadpool? If this is an issue, then fire the coroutines from another coroutine. :)

Android Jetpack: lifecycle-aware recurrent periodic task execution with LiveData and ViewModels

My app already uses some recent Android patterns for network calls:
LiveData class
MVVM architecture with ViewModel class
Kotlin coroutines for Repository classes
Retrofit interface etc.
Now I want to implement common feature which is automatic fetching current data from API every few minutes.
I read about WorkManager and give it a shot - I implemented it but I then saw that WorkManager (JobScheduler) keeps running after closing app which is not what I want. I also felt like WorkManager API is too much overkill for that simple task.
Then I read a guide on Codepath that suggests Handler class for main thread repetitive jobs and ScheduledThreadPoolExecutor for background repetitive tasks. I know that they will probably work fine but I'm not sure if they are best solution.
My question is: what's currently the best way for recurrent API calls that:
works with LiveData and ViewModel classes (observable result like normal API call)
is Kotlin-friendly (any way to make coroutine recurrent?)
is "lifecycle-aware", meaning that it will stop when app goes to the background?
WorkManager is for guaranteed works that needs to be executed even if your app exit or the device is restarted. From your description this doesn't seem your use case.
A threadpool seems the best option in this case, but you can judge yourself starting from this guide: "Background Tasks".

Advantage of RxJava2 over AsyncTask

Hi I am reading about rxjava2 which is basically for async operations. I found it has an operator concept which AsyncTask in android does not.
How else is rxjava2 different than AsyncTask?
RxJava is not "basically for async operation". That is only one aspect of it.
RxJava allows you to compose operations on data, such that the output of one operation can be used as the input to the next. This operates similarly to streams implementations.
RxJava uses this composability to allow some operations to occur in a multi-threaded environment. It does this by providing well-defined semantics for the operators when working with multiple schedulers. RxJava can use asyncTask to perform some operations.
RxJava manages back pressure requirements for some applications by using Flowable chains, while Observable chains have no back pressure requirements. The former is appropriate where buffering is required or explicit acknowledgment of dropped information needs to be made.
RxJava has clear error and error handling semantics.
asyncTask just handles asynchronous tasks.
AsyncTask is Android’s default tool for developers needing to do some simple long-ish running work in the context of a UI screen without blocking the UI.
The main problem with AsyncTask is:
MULTIPLE WEB SERVICE CALLS:
To solve this in AsyncTask create an inner AsyncTask subclass in our Activity/Fragment, perform the network operation in the background, and take the result of that operation and update the UI in the main thread.
this approach has some issues and limitations:
Memory/context leaks are easily created is an inner class and thus holds an implicit reference to the outer class Also, what if we want to chain another long operation after the network call? We’d have to nest two AsyncTasks which can significantly reduce readability.
ERROR HANDLING
What happens if something goes wrong? Unfortunately, there’s no out-of-the-box solution for this.
And other problem like device rotation, back press handle etc.
To solved this all problem look at RxJava
Handle Error using RxJava is like this:
webService.doSomething(someData)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
result -> resultText.setText("It worked!"),
e -> handleError(e));
Second, In multiple web services call.
public Observable<List<Weather>> getWeatherForLargeUsCapitals() {
return cityDirectory.getUsCapitals()
.flatMap(cityList -> Observable.from(cityList))
.filter(city -> city.getPopulation() > 500,000)
.flatMap(city -> weatherService.getCurrentWeather(city)) //each runs in parallel
.toSortedList((cw1,cw2) -> cw1.getCityName().compare(cw2.getCityName()));
}
Hope this may help you!!

Is there a way to get all ongoing AsyncTasks?

I am writing a few tests for Android code that does business logic and triggers asynchronous db operations through the Sprinkles library. My tests are basically failing when they expect certain data to be present in db, but the data is missing due to the async writes not being completed yet. Therefore, for testing purposes, it seems that I need a way to wait for the async jobs to be finished before I do my assertions.
After taking a look at how Sprinkles does the asynchronous writes, it simply triggers a new AsyncTask. But these AsyncTasks are completely handled by Sprinkles so I do not have access to them. So I was wondering: is there a way to get hold of all ongoing AsyncTasks started by my application? If there is, then I can make my tests wait for all AsyncTasks to be completed. Not a great solution, but it would do the trick.
Otherwise, does anyone have any tips on how to tackle this problem?
Thanks a lot!
You can use
Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();
then go over each stack traces and look for async tasks and see if they are in
doInBackground
method
I had to do something similar, I decided to keep Boolean variables to represent if they had completed or not. and check on the OnPostExecute method of every Async task if all had finished or not and if all had then set a boolean variable representing that.

should you create new Async Tasks for every different call or use the same one

So I have an app that will make multipe HTTP Post/Gets
E.G. Login, getThisData, getThatData, sendThis, sendThat
Is it better to have a seperate AsyncTask to handle each one
Or one async task and process them differently with a switch in onPostExecute and doInBackground
Cheers
Short answer is yes you should create a new AsncTask for each call.
And if you interested, the long answer is;
According to the Android's Asynctask documentation,
The goal of the AsyncTask is to take care of thread management for you and you should not worry about the threading mechanisms.
The Android Platform handles the pool of threads to manage the asynchronous operations. AsyncTasks are like consumables. The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Happy asynchronous coding! :-)
It depends on whether the tasks are independent on each other or whether they are interrelated. If independent you can handle this through the same async. For ex if you need some data from your login response and pass that value to getthis task you better use separate async.
Make login a separate async, getthis ,get lthat sendthis sendthat can be in one async.
You'll probably want to separate them, especially if their functionality in the pre/post executes differs. Try to organize your code into logical blocks. For example, if you have an Async Task to Login, and an Async task to, for example, download lots of document data via JSON, they will want separate Async tasks.
However, lets say you have two separate API calls that return similar or partially the same data - if one returned the details of a file (name, size) and the other returned the same data but was a revision of a file - you could switch these in the same ASYNC because the post execute is going to perform the same (or partially the same) code to extract data from the JSON.
If you want to create one instance of AsyncTask, and execute() it several times, no:
Execute AsyncTask several times
If you are asking about designing: whether you should write one class to get different kind of data? It really depends on your circumstances:
If these HTTP call supposed to be sequential, you can put them in one AsyncTask class.
If they have lot in common, just point to different URIs, you can write a call(String uri) method, and invoke that method in your AsyncTask. This case, I think one AsyncTask is also enough.

Categories

Resources