I know that execute() is a synchronous function which means Until you are able to use it should execute it in other threads.
But I want to understand why would I use execute function even though enqueue function exists that does this work (execute on other thread) itself.
what are cases that should use execute function in it?
Sometimes, you are already on a background thread, supplied by something else:
JobIntentService
WorkManager
Kotlin coroutines
RxJava
Etc.
In those cases, you may not need OkHttp or Retrofit to use yet another background thread and can use execute() for simpler code.
Related
I have read one article which says the following :
* Room will provide main-safety automatically if you use suspend functions, RxJava, or LiveData.
** Networking libraries such as Retrofit and Volley manage their own threads and do not require explicit main-safety in your code when used with Kotlin coroutines.
So I have two questions :
If i will have one suspend function inside viewmodel and it's having long running task inside it and it does not use any dispatcher. So if I will call this function from activity/fragment, then will it work as simple function as we have not defined any dispatcher and will block the ui ?
As stated above in the statements, for room/retrofit, should we use dispatcher explicitly(like IO in these cases) as they are taking care of background thread by themselves.
Googled it, did not get exact answer, so posting to get clarity.
Yes, the suspended function will run normally & will not block the UI unless you use a blocking coroutine like runBlocking or withContext that returns a value to the UI.
A simple launch i.e. viewModelScope.launch would not block a thread.
As per the docs they use a custom dispatcher to handle threading.
From the code-lab docs:
Both Room and Retrofit make suspending functions main-safe.
It's safe to call these suspend funs from Dispatchers.Main, even though they
fetch from the network and write to the database.
Both Room and Retrofit use a custom dispatcher and do not use
Dispatchers.IO.
Room will run coroutines using the default query and
transaction Executor that's configured.
Retrofit will create a new Call object under the hood, and call
enqueue on it to send the request asynchronously.
As my understand,
When you call suspend function, you need to provide a coroutine scope. So, if you provide Dispatcher.Main or MainScope, it will block UI.
Room/Retrofit has implicit coroutine scope. That means you don't need provide it for them. But when you call to Room/Retrofit, you will need to provide coroutine scope like [1]
I'm trying to implement a call screening service in my app. It seems the CallScreeningService class has really a bad design however. The abstract method onScreenCall is called on UI thread and it's not possible to use something different, in addition the method respondToCall must be called in onScreenCall because it's not possible to go async looking at AOSP source code. The code calls recycle() on onScreenCall arguments when it returns. The question: how is it supposed to work? We can't bind another service, we can't use an AsyncTask, even a load from database would be a problem since the access is performed on UI thread. Am I missing anything?
You can use rxjava or coroutines to access your data in background thread
Is Retrofit .execute method is already background task or should I call this method in AsyncTask in retrofit official documentation it mentions that callbacks executed in mainThread, but its not clear if execute method is background task.
Retrofit documentation:
SYNCHRONOUS VS. ASYNCHRONOUS
Call instances can be executed either synchronously or asynchronously. Each instance can only be used once, but calling clone() will create a new instance that can be used.
On Android, callbacks will be executed on the main thread. On the JVM,
callbacks will happen on the same thread that executed the HTTP
request.
call.execute() //not a background task, works in the foreground(synchronous).
call.enqueue() //This is a background task(asynchronous).
call.execute() runs the request on the current thread.
call.enqueue() runs the request on a background thread, and runs the callback on the current thread.
This link has a nice explanation on what you are asking for. In short Asynchronous requests will have callbacks like onResponse and onFailure. If you are making request to API, you would certainly want to go with asynchronous.
I have really searched for this every where, I can make both synchronous and asynchronous data requests, but I can't actually understand which is asynchronous with what? and what is sync with what?
call.execute() runs the request on the current thread.
call.enqueue(callback) runs the request on a background thread, and runs the callback on the current thread.
You generally don't want to run call.execute() on the main thread because it'll crash, but you also don't want to run call.enqueue() on a background thread.
when you asynchronous, it means not in the foreground(it does not block the users interface while it accomplishes the given task), on other hand synchronous means in the foreground while your application execute things in the same thread the UI consuming.
In your case(making REST requests via retrofit or any other REST api) you must not make that in that foreground and you have to make in a background thread.
In the case of retrofit you have the following methods to make the request:
call.execute() // works in the foreground.
call.enqueue() // works in the background.
So you have a choice of two: either you make the call.enqueue directly or you can user call.execute but wrapped with a service(I mean you have to handle the background work your self).
Synchronous requests are declared by defining a return type.Synchronous methods are executed on the main thread. That means the UI blocks during request execution and no interaction is possible for this period. Using the .execute() method on a call object will perform the synchronous request. The deserialized response body is available via the .body() method on the response object.
Asynchronous requests don’t have a return type. Instead, the defined method requires a typed callback as last method parameter.Using asynchronous requests forces you to implement a Callback with its two callback methods: success and failure. When calling the asynchronous getTasks() method from a service class, you have to implement a new Callback and define what should be done once the request finishes.
Retrofit is a type-safe HTTP client for Android and Java. And I would highly recommend using this over any other library.
Do you understand what is sync and async call, or what is blocking and non-blocking call?
To answer your question, any api call you do or any heavy or time-consuming task you do on Android, it should be non-blocking (async) as it should not block the Main or UI thread in Android.
Please read this article for more understanding
https://developer.android.com/guide/components/processes-and-threads.html
I would like to run asynchronous server call using AsyncTaskLoader. Method loadInBackground() should return the result synchronously. I am returning null and I call deliverResult() in callback which is executed on manually created HandlerThread. This implementation is sending to UI null at first, then (when async server operation is done) real data. I'm not sure this is good solution.
How to implement custom AsyncTaskLoader properly, where I want to load data by asynchronous server calls (thus using callbacks)?
Thanks for any help
use join() on manually created HandlerThread (without code it's hard to give a working example)