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!!
Related
What is the reason behind viewModelScope defaulting to MainThread when most of the use cases are using as a background thread?
I still can't think of one example in my project that require using the main thread in ViewModel.
Also, is there a better/shorter way than writing as below?
viewModelScope.launch(Dispatchers.Default) {
// codes here
}
Couple of reasons:
ViewModel is probably the closest layer to the UI, which means a lot of logic here is involved in updating the UI => launching in any other thread will mean that you'll have to switch back to the Main for updating things
Using any other dispatcher implies, that one knows what kind of operations will happen in the VM (like IO operations or some computing maybe?)
In general I think it's a good practice, to not handle thread switching in your VM and handle on the layer, which essentially knows what kind of operation will be run.
For example if you have a VM -> Repository -> LocalSource (database operations) & RemoteSource (networking), then I'd do the switching to the IO thread in the Remote and Local sources.
Reactive programming with RxJava helps create nice and concise code for business processes that include UI dialogs and long-running async tasks. However, Android UI has its peculiarities that can break the process. A simplified example:
public void onProcessWasInitiatedByUser() {
someCompletableSource.startAndWaitForSomeLongProcess()
.flatMap(showModalDialogAndWaitForAnswer())
.flatMap(startAndWaitForSomeOtherLongProcess())
.flatMap(showAnotherModalDialogAndWaitForAnswer())
.subscribe(() -> {
// finalize the process after the user has entered and confirmed all the required data
});
}
Note: subscribeOn() and observeOn() not included in the example for brevity. I know that mixed UI + background processes will require thread switching to avoid UI freezes and direct UI calls from background threads.
The questions:
Considering that startAndWaitForSomeProcess might last long enough for the device to go to sleep, there is a very high chance to get a java.lang.IllegalStateException if attempting to show a modal dialog. How to ensure that modal dialog is displayed when the user unlocks the device, but still to keep the modal dialog as part of this Rx flow?
In theory, I've heard it is recommended to use viewmodels to solve UI lifecycle issues but I'm not sure how it would help in this situation. Ok, I can store the data inside a viewmodel and later show the dialog when the device wakes up... but then how do I continue with the same Rx flow that was started in onProcessWasInitiatedByUser? I would prefer not to break the flow into separate pieces and scatter them around some other event handlers. What should I do inside showModalDialogAndWaitForAnswer function to make them safe for locked screen cases and still wait for the answer from the user?
Less important - I'm not sure if my example is the nicest way to organize this. Is there any rule of thumb, when things should go inside flatMap and when should be left for the final subscribe, or when subscribe should be left entirely empty; or when it's best to use some different RxJava function? How do experienced RxJava developers organize it to avoid ambiguities and possible caveats?
Great questions. Here my observations:
startAndWaitForSomeProcess is an operation that should be executed in the background and a separate context that, once finished, notify the client (View). In this case, what you need is probably a background task or a Service.
Rx helps you to orchestrate both synchronous and asynchronous processes in the same or different Scheduler contexts. I do not recommend using it for this requirement since it would imply an extended UI blocking time, and the operations life cycle would be unmanageable.
It is recommended that conversations with UI be made through the subscribed Observer, not through the operator's chain, as side effects may induce bugs. I've written a useful guide called "The Clean Way to Use Rx," and in Item 33: Negotiating with UI, it talks about it.
I hope that I have helped you.
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.
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. :)
Hi guys I have a question about Asyntask which is used in android studio :
As far as I know AynTask is used for user interface via one thread, the so called UI Thread. If you perform a long running operation directly on the UI Thread, for example downloading a file from the internet, the user interface of your application will “freeze” until the corresponding task is finished.
But let's say that I want to register an account so that I can login, that shouldnt take time at all so why should I use Asyntask for this?
Let's say I want to send 100 strings to the Database, that can be done in milisecs I think, so again, why to use and how to decide when to use Asyntask?
I hope you guys can help me out, I have been searching for a long time !
If you don't know how much time operation will take, you should perform it in a separate thread and then pass the results to UI thread. I think the database should be accessed in a separate thread as well as HTTP requests. In the case of time-consuming query, it may be a long operation. AsyncTask is one way to do it. You can also use other techniques. The popular technique used nowadays is applying RxJava library, which gives you the high-level functional reactive interface for writing multi-threaded applications with a few additional features. You can perform an operation in e.g. Sechdulers.io() (I/O) thread and then pass the result to AndroidSchedulers.mainThread(), which is UI thread.
There are also other techniques like using Looper & Handler from Android SDK or using Thread class from Java, but such techniques require more knowledge, more work, writing more boilerplate code & you have more problems to deal with.