Kotlin coroutines Inappropriate blocking method call (tcp sockets) - android

I'm getting this warning when working with sockets. I'm calling the startConnection method from IO scope coroutine and if the startConnection method is suspend I get the warning. I make it a suspend, because later I'm calling some other suspend methods from it. Is there any way around this or should I suppress the warning?
private suspend fun startConnection(ip: String, port: Int) {
try {
socket = Socket(ip, port)
.
.

Socket() is a IO call. it's making a actual TCP connection.
In fact, all the calls in the "old IO" framework are blocking calls. You need to allocate a thread for each call (or be ok w/ things locking up for a bit)
coroutines != threads
If you use Dispatch.IO then coroutines == threads (sorta of, but hidden from you), but the compiler doesn't know that's the dispatcher your using so you'll continue to get the same error. If your 100% sure your coroutine is on it's own thread than just ignore it.
Some unsolicited advice : If your using coroutines like threads, maybe it'd be better to just use threads? Using coroutines just seems to be making your life harder (this error for example). If your using Dispatch.IO your going to have to synchronize stuff anyway, just like a thread. Not sure what coroutines is buying you here.
coroutines are just a compiler trick to split your code up and make callbacks out of suspend calls w/o you knowing it. I think of them as cooperative-threading from Windows 3.1 from 1994 (what's old is new again).
You want to get into the sprit of coroutines use the NIO calls. The Async versions are easier to use (you don't have to write you own select() loop). Or use Netty, which is all callbacks all the time, and wrap you coroutines around that (there must be a lib that does that by now...)

Related

Coroutines and suspend related to main thread and dispatcher

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]

Kotlin Coroutines. what is in charge of suspend function? how many thread could get involved when working with coroutines?

I have a couple questions on kotlin coroutines.
how many thread could get involved when working with coroutines?
if we use just Dispatchers.Main, would only one thread get involved(single threaded)? if we use Dispatchers.IO, would multiple thread possibly get involved (maximum of 64 threads)?
what will be the use case for using Dispatchers.Main? most articles that I have read say all UI related works should present in Dispatchers.Main and background related works(like reading/writing data from/to database, network requests) needs to present in Dispatchers.IO but I don't understand what UI related works present in Dispatchers.Main since UI related work don't really necessary need coroutines (with Dispatchers.Main)
we use susepnd fuction with coroutines for some works that could block the current thread. For example, read data from disk, network requests, or high tense computation etc. if these works are executed by suspend function, what/who is in charge when these functions are suspended? I think something has to be working on these suspend functions anyway. will that be background threads that is in charge of below?
reading/writing data from/to databse
waiting for network request
computing high tense computation
please point out if my wording or questions are incorrect.
Thank you in advance.
I think you answered yourself. Short answer is: Dispatchers.Main - single thread, Dispatchers.Default - number of cores, Dispatchers.IO - at most 64. You can read about it here. Full answer is a little more complicated as limits could be reconfigured, they may differ on different platforms (e.g. JavaScript is always single-threaded), Default partially shares threads with IO, etc. We can also create our own thread pools.
I'm not sure what do you mean. Coroutines are generally never necessary in order to do anything. But if we use coroutines inside UI application, then we should use Dispatchers.Main for UI-related stuff.
We should almost never use blocking code inside coroutines (one exception is Dispatchers.IO). If we do that, the coroutine won't suspend, but just block, possibly making other parts of our application unresponsive or degrading the performance.

best way for running code in async with kotlin

hi i want use jsoup to load a large table from html, what is the best way for doing this in async way?
AsyncTask? coroutines? doasync library? which one? i need show progressbar while fetching data so please tell me what is the best way?
UPDATE:
i want run this code in async
doc: Document = Jsoup.connect(url).timeout(0).maxBodySize(0).ignoreHttpErrors(true).sslSocketFactory(setTrustAllCerts()).get()
// some code for parsing...
In Kotlin, the general approach is coroutines, but normal threading is also a completely fine option, depending on what you're doing.
For example, if your operation is a thread-blocking operation, it actually can't run safely in a coroutine unless it's dispatched in a separate thread. For coroutines, you need to know the difference between suspending and blocking (huge difference).
So if reading the HTML table is a blocking operation, and you don't need to integrate with other coroutines, then a normal thread works just fine. There are many Java examples that are transferable to Kotlin.
With coroutines, you can do something like:
suspend fun getDoc() = withContext(Dispatchers.IO) {
Jsoup.connect(url).timeout(0).maxBodySize(0).ignoreHttpErrors(true).sslSocketFactory(setTrustAllCerts()).get()
}
Then, in your main code:
fun main() = runBlocking {
val deferredDoc = async { getDoc() }
// Do whatever.... it's not being blocked...
val doc = deferredDoc.await() // SUSPENDING CALL - but not blocking
}
Obviously, your program's structure will look different than this example, because it depends entirely on what code you want to execute asynchronously with "getDoc()".
For example, you can even have another coroutine that executes while "deferredDoc.await()" is suspending, without even creating another thread. That's the benefit of coroutines.
In the structure above, we have 3 guaranteed threads:
Main thread, which is always blocked
Main Coroutine thread. This is what the coroutines generally run on. Kotlin coroutines will run your coroutines asynchronously inside this thread using suspension.
IO thread. This is what your blocking code will run on.
I'll advice you try out Kotlin Coroutines. This would enable you dispatch expensive or long-running operations i.e. querying databases, making network requests/calls off to other threads thereby not blocking the Main Thread. Coroutines help you avoid the hassle of callbacks. Also, Google deprecated the AsyncTask API (in Android 11) and recommends using Java’s Concurrency framework or Kotlin Coroutines as the way to go for multi-threading purposes.

How does a Coroutine Continuation internally work?

I have been working with coroutines for few weeks and sometimes its tough to understand the real working difference between thread concurrency and coroutine concurrency.
How suspend functions works internally ? How is continuation block helping in resuming the computation after suspension.
How is sequential computation of the line of code inside coroutine not blocking the thread ? and how is it better than thread concurrency ?
How suspend functions works internally?
Briefly, on the Java platform a suspend fun compiles into bytecode that is dramatically different from a plain function. It receives a hidden extra parameter (the continuation), creates its own continuation object, and the entire body of the function is implemented (approximately) as a big switch statement that allows the function to jump into the middle of the body when resuming.
When a suspend fun suspends, the underlying Java method actually returns. The return value is a special COROUTINE_SUSPENDED singleton object which the framework knows how to interpret. It is the responsibility of the suspend fun itself to save the continuation object where it will be accessible when the result of the function is ready.
The official documentation has a good in-depth description of these details.
How is continuation block helping in resuming the computation after suspension.
This is related to what I said above, that the suspend fun itself is responsible for ensuring it gets resumed later on. It must do that inside the block provided by the function suspendCoroutineOrReturn. User code doesn't call it directly, but the more high-level analogs suspendCoroutine and suspendCancellableCoroutine. These take over the concern of resuming the coroutine on the appropriate thread and the developer is responsible only for ensuring that continuation.resume() is called with the result when it becomes available. This typically happens in a callback you pass to an async call.
You can study this answer that tries to explain the suspend-resume mechanism in a self-contained example.
How is sequential computation of the line of code inside coroutine not blocking the thread?
Because it actually compiles into returning from the function and later on resuming by jumping into the middle of the function body.
and how is it better than thread concurrency?
Native threads are heavyweight resources that take time to create and destroy. Coroutines are much lighter-weight and consequently you can start many more of them, and more quickly.
The internal workings are explained in the original design document https://github.com/Kotlin/KEEP/blob/master/proposals/coroutines.md which has a section on "Implementation Details".

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. :)

Categories

Resources