I'm fairly new to RxJava so this is probably a dumb question. I am going to describe my scenario.
I have some code running on the UI thread which will update some images but those images are not very important and they consume a bit of resources while generating them so I want to generate them on a single thread (not the UI thread of course) and generate them one by one. I'm guessing the trampoline scheduler is what I want but my problem is that if I use it then it does the work on the UI thread and I want it to do it on another thread.
Obviously I can write my own thread in which I can queue items and then it processes those one by one but I thought maybe RxJava would have a simple solution for me?
My current code looks like this:
Observable<Bitmap> getImage = Observable.create(new Observable.OnSubscribe<Bitmap>() {
#Override public void call(Subscriber<? super Bitmap> subscriber) {
Log.w(TAG,"On ui thread? "+ UIUtils.isRunningOnUIThread());
subscriber.onNext(doComplexTaskToGetImage());
subscriber.onCompleted();
}
});
getImage.subscribeOn(Schedulers.trampoline()).subscribe(new Action1<Bitmap>() {
#Override public void call(Bitmap bitmap) {
codeToSetTheBitmap(bitmap);
}
});
My log that says "On ui thread?" always has true. So how do I make that code and all subsequent attempts to do the same thing run on a single thread (not the ui thread) in order without writing a bunch of code to queue that work?
Edit:
I believe that this can now be accomplished using Schedulers.single() or if you want your own you can use new SingleScheduler(). I'm still testing but I think it does what I wanted back when I posted this.
You can create a single reusable thread to create a Scheduler for the Observable in one of the following ways:
Create a ThreadPoolExecuter with a pool size of 1 (Executors.newSingleThreadExecutor() is a convenient static factory method for doing that), then use it to generate the schedulers via the Schedulers.from() method.
RxAndroid provides a custom Scheduler implementation that uses a Handler to schedule the actions, and thus can be used with any Thread that has a Looper running by passing it's Handler to the AndroidSchedulers.handlerThread() factory method.
Note that you will need to observe on a main thread Scheduler if you're interacting with the UI at the conclusion of these tasks.
In RxJava 2 you can use Schedulers.single() which:
Returns a default, shared, single-thread-backed Scheduler instance for
work requiring strongly-sequential execution on the same background
thread.
Please see the documentation for more details.
I don't see it available in RxJava 1 Schedulers documentation.
You are using trampoline scheduler, so it means your source observable will be run on the current thread (here is main thread).
And the subscribeOn will work for both upstream and downstream. That why your log shows your are running on the main thread
To fix this, you can use Schedulers.single() in the subscribeOn, and then observeOn the main thread.
Related
This is one of the most confusing topics for me. So my question is, what is the correct way of communicate the result of background thread when this finish?.
Imagine I want to update some TextView with some information I just downloaded.There is 3 things I use when I need to perform background tasks:
AsyncTask
Very easy to use, this one has the onPostExecute() method that will return the result directly to the UiThread so I can use a callback interface or do whatever I want. I liked this class but it's deprecated.
ThreadPoolExecutor
This is what I actually use when need to perform background tasks and here comes my problem, the moment when I have to give the result to the UiThread. I have informed myself about Looper and Handler classes and about the mainLooper.
So, when I need to return some results I use the method runOnUiThread() that, as I have readed, just get the Looper of the Ui thread and post my Runnable to the queue.
Well this is working and I can communicate with the main thread but, I find it really ugly, and I am sure there is a more elegant way of doing it than populate all my code of "runOnUiThread()" methods. Also, if the background task need too much time, maybe the user already change of Activity or Fragment when the code inside runOnUiThread() runs what will cause Exceptions (I know using LiveData and MVVM pattern would solve this last problem but I am working in a legacy project and I can't refactor all the code so I am working with the clasical Activity mvc pattern)
So, there is another way of doing this? Could you give an example? I really searched a lot but didn't find anything...
Coroutines
I am actually working in a legacy project and I must use Java so can't use Kotlin coroutines, but I find them easy to use and so powerfull.
Any help would be appreciated!
Background
In Android, when an application is launched, the system creates a thread of execution for the application, called main thread (also known as the UI thread). Google introduces the main thread and its responsible as below.
The main thread has a very simple design: Its only job is to take and
execute blocks of work from a thread-safe work queue until its app is
terminated. The framework generates some of these blocks of work from
a variety of places. These places include callbacks associated with
lifecycle information, user events such as input, or events coming
from other apps and processes. In addition, app can explicitly enqueue
blocks on their own, without using the framework.
Nearly any block of code your app executes is tied to an event
callback, such as input, layout inflation, or draw. When something
triggers an event, the thread where the event happened pushes the
event out of itself, and into the main thread’s message queue. The
main thread can then service the event.
While an animation or screen update is occurring, the system tries to
execute a block of work (which is responsible for drawing the screen)
every 16ms or so, in order to render smoothly at 60 frames per second.
For the system to reach this goal, the UI/View hierarchy must update
on the main thread. However, when the main thread’s messaging queue
contains tasks that are either too numerous or too long for the main
thread to complete the update fast enough, the app should move this
work to a worker thread. If the main thread cannot finish executing
blocks of work within 16ms, the user may observe hitching, lagging, or
a lack of UI responsiveness to input. If the main thread blocks for
approximately five seconds, the system displays the Application Not
Responding (ANR) dialog, allowing the user to close the app directly.
To update a View, you must do it on the main thread, if you try to update in a background thread, the system will throw CalledFromWrongThreadException.
How to update a View on the main thread from a background thread?
The main thread has a Looper and a MessageQueue assigned with it. To update a View, we need to create a task then put it to the MessageQueue. To do that Android provides
Handler API which allows us to send a task to the main thread's MessageQueue for executing later.
// Create a handler that associated with Looper of the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());
// Send a task to the MessageQueue of the main thread
mainHandler.post(new Runnable() {
#Override
public void run() {
// Code will be executed on the main thread
}
});
To help developers easy to communicate with the main thread from a background thread, Android offers several methods:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Under the hood, they use Handler API to do their jobs.
Back to your question
AsyncTask
This is a class that is designed to be a helper class around Thread and Handler. It's responsible for:
Create a thread or pool of thread to do a task in the background
Create a Handler that associated with the main thread to send a task to the main thread's MessageQueue.
It is deprecated from API level 30
ThreadPoolExecutor
Create and handle a thread in Java is sometimes hard and might lead to a lot of bugs if developers do not handle it correctly. Java offers the ThreadPoolExecutor to create and manage threads more efficiently.
This API does not provide any method to update the UI.
Kotlin Coroutines
Coroutines is a solution for asynchronous programming on Android to simplify code that executes asynchronously. But it only available for Kotlin.
So my question is, what is the correct way of communicate the result
of background thread when this finish?.
1. Using Handler or mechanism built on Handler
1.1. If a thread is bounded with Activity/Fragment:
Activity.runOnUiThread(Runnable)
1.2. If a thread has a reference to a view, such as Adapter class.
View.post(Runnable)
View.postDelayed(Runnable, long)
1.3. If a thread does not bound to any UI element, then create a Handler on your own.
Handler mainHandler = new Handler(Looper.getMainLooper);
Note: A benefit of using Handler is you can use it to do 2 ways communication between threads. It means from a background thread you can send a task to the main thread's MessageQueue and from the main thread, you can send a task to the background's MessageQueue.
2. Using BroadcastReceiver
This API is designed to allow Android apps can send and receive broadcast messages from the Android system, other apps or components (Activity, Service, etc) inside the app, similar to publish-subscribe design partern.
Because of the BroadcastReceiver.onReceive(Context, Intent) method is called within the main thread by default. So you can use it to update the UI on the main thread. For example.
Send data from a background thread.
// Send result from a background thread to the main thread
Intent intent = new Intent("ACTION_UPDATE_TEXT_VIEW");
intent.putExtra("text", "This is a test from a background thread");
getApplicationContext().sendBroadcast(intent);
Receive data from activity/fragment
// Create a broadcast to receive message from the background thread
private BroadcastReceiver updateTextViewReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String text = intent.getStringExtra("text");
myTextView.setText(text);
}
};
#Override
protected void onStart() {
super.onStart();
// Start receiving the message
registerReceiver(updateTextViewReceiver, new IntentFilter("ACTION_UPDATE_TEXT_VIEW"));
}
#Override
protected void onStop() {
// Stop receving the message
unregisterReceiver(updateTextViewReceiver);
super.onStop();
}
This method is usually used to communicate between Android apps or Android apps with the system. Actually, you can use it to communicate between components in Android app, such as (Activity, Fragment, Service, Thread, etc.), but it requires a lot of code.
If you want a similar solution but less code, easy to use, then you can use the following method.
3. Using EventBus
EventBus is a publish/subscribe event bus for Android and Java. If you want to execute a method that runs on the main thread, just mark it with #Subscribe(threadMode = ThreadMode.MAIN) annotation.
// Step 1. Define events
public class UpdateViewEvent {
private String text;
public UpdateViewEvent(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
// Step 2. Prepare subscriber, usually inside activity/fragment
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
myTextView.setText = event.getText();
};
// Step 3. Register subscriber
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
// Step 4. Unregister subscriber
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
// Step 5. Post events from a background thread
UpdateViewEvent event = new UpdateViewEvent("new name");
EventBus.getDefault().post(event);
This is useful when you want to update a View when the activity/fragment is visible to users (they are interacting with your app).
Since the very beginning (API 1) the android way of communication between threads has been Handler. Actually AsyncTask is just a wrapper around a thread pool and it uses Handler also to communicate to the main thread, you can check out the source code and create you own wrapper similarly.
Handler is the very low-level primitive and I wouldn't say using Handler is ugly, but it definitely requires some knowledge of multithreading programming and makes the code more verbose. As you also mentioned there are a lot of issues arises, like your UI can be gone by the time the task is completed and you have to handle this on your side. That's always the case with the low-level primitives.
As you are looking for reputable sources, here is the official documentation on exactly this problem - communicating a result from background thread to the main thread in plain java.
So unfortunately there is no other - better and officially recommended - way of doing that. Of course there are plenty of java libraries like rxJava that are build on top of the same primitives but provides higher level abstractions.
I personally use AsyncTask like this:
Setup a broadcastReceiver in my Activity or Fragment
Call the asyncTask with any needed arguments in an Object[] using the Executor of your choice.
Once the AsyncTask has completed I Bundle with the data or result, send a LocalBroadcast containing this bundle.
In my Fragment or activity receive the broadcast and handle the result.
I have never had any issues with this method, I do understand some people are shying away from AsyncTask, but for most purposes and all I have come across this is a simple and reliable method.
I am using the Unity game engine which also supports exporting to Android.
The engine uses multiple threads, including the UI thread and a separate scripting thread where all the user custom code is executing.
My scenario requires that i call some operation in a background thread, and i would like to marshal the result back to the main scripting thread.
I know the basics of the AsyncTask, Executor and Looper classes. Out of these, Looper seems like a good candidate since it allows setting up a queue and post back messages to a given thread (AsyncTask is "hardwired" to run the callback on the UI thread, which is not what i want here).
What is the proper way of achieving this?
There is 3 main ways to communicate with the UI thread :
Activity.runOnUiThread(Runnable)
View.post(Runnable)
Handlers
In your case, I advice you to create an Handler, as the 2 first solutions imply that you have a reference on your Activity or a View
Edit
If you want to use any thread in your app, just make sure a Looper has been set, and use an associated Handler
class YourLooperThread extends Thread
{
// make it accessible from the outside
private Handler handler;
#Override public void run()
{
Looper.prepare();
// Customize your handler, it has to be used in any thread which want to push a message in this thread's looper message Queue
handler = new Handler();
Looper.loop();
}
}
Be careful : all the other tasks you want to do in that thread must be done through the message queue, i.e posting a runnable in the handler. More information here : Handlers, MessageQueue, Looper, do they all run on the UI thread?
I'm pretty confused about the concept of Task/Service in JavaFX.
I have used a model based on a background thread for my background work, which call Platform.runLater for any update to the UI.
Let's say I'm not interested in a progress bar or such. I'm doing some real work on my model that must be updated in the view of the GUI (e.g a list of participants which updates over time based on some connection in the background, list of participant based on some user input, classified by age and origin). This is what I usually achieve with background threads that I start, and within which I use Platform.runLater.
Now in JavaFX 2 they have all this concurrency using Tasks and Services, suggesting that it is better to use them. But I don't see any examples that achieve what I'm talking about.
Updating the progress bar by binding some properties is nice (but those are information on the task not your model).
So, how can I actually update the content of my views based on my model? Should I call Platform.runLater from within the Task? If not, what is the mechanism? How do I catch when the tasks have succeed and get the result (the update of the actual model) to update the view?
The tutorials by Oracle unfortunately were not very good in this regard. Pointing me to some good tutorials would also help.
The Task and Service classes are designed to encourage good practice and proper use of concurrency for some (but not all) common scenarios in GUI programming.
A typical scenario is that the application needs to execute some logic in response to a user action which may take a long time (maybe a long calculation, or, more commonly, a database lookup). The process will return a result which is then used to update the UI. As you know, the long-running process needs to be executed on a background thread to keep the UI responsive, and the update to the UI must be executed on the FX Application Thread.
The Task class provides an abstraction for this kind of functionality, and represents a "one-off" task that is executed and produces a result. The call() method will be executed on the background thread, and is designed to return the result of the process, and there are event listeners for when the task completes that are notified on the FX Application thread. The developer is strongly encouraged to initialize the Task implementation with immutable state and have the call() method return an immutable object, which guarantees proper synchronization between the background thread and the FX Application Thread.
There are additional common requirements on these kinds of tasks, such as updating a message or the progress as the task progresses. The application may also need to monitor the life-cycle state of the class (waiting to run, running, completed, failed with an exception, etc). Programming this correctly is quite subtly difficult, as it necessarily involves accessing mutable state in two different threads, and there are many application developers who are unaware of the subtleties. The Task class provides simple hooks for this kind of functionality and takes care of all the synchronization.
To use this functionality, just create a Task whose call() method returns the result of your computation, register a handler for when the state transitions from RUNNING to SUCCEEDED, and run the task in a background thread:
final Task<MyDataType> task = new Task<MyDataType>() {
#Override
public MyDataType call() throws Exception {
// do work here...
return result ;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent event) {
MyDataType result = task.getValue(); // result of computation
// update UI with result
}
});
Thread t = new Thread(task);
t.setDaemon(true); // thread will not prevent application shutdown
t.start();
The way this works behind the scenes is that the Task maintains a state property, which is implemented using a regular JavaFX ObjectProperty. The Task itself is wrapped in a private implementation of Callable, and the Callable implementation is the object passed to the superclass constructor. Consequently, the Callable's call() method is actually the method executed in the background thread. The Callable's call() method is implemented as follows:
Schedule a call on the FX Application thread (i.e. using Platform.runLater()) that updates the state, first to SCHEDULED, then to RUNNING
Invoke the call() method of the Task (i.e. the user-developed call() method)
Schedule a call on the FX Application Thread that updates the value property to the result of the call() method
Schedule a call on the FX Application Thread that updates the state property to SUCCEEDED
This last step will of course invoke listeners registered with the state property, and since the state change was invoked on the FX Application Thread, so to will those listeners' handle() methods.
For a full understanding of how this works, see the source code.
Commonly, the application may want to execute these tasks multiple discrete times, and monitor the current state representing all of the processes (i.e. "running" now means one instance is running, etc). The Service class simply provides a wrapper for this via a createTask() method. When the Service is started, it gets a Task instance by calling createTask(), executes it via its Executor, and transitions its own state accordingly.
There are of course many concurrency use cases that don't fit (at least cleanly) into the Task or Service implementations. If you have a single background Thread that is running for the entire duration of your application (so it represents a continuous process, rather than a one-off task), then the Task class is not a good fit. Examples of this might include a game loop, or (perhaps) polling. In these cases you may well be better off using your own Thread with Platform.runLater() to update the UI, but of course you have to handle proper synchronization of any variables that may be accessed by both threads. In my experience, it is worth spending some time thinking about whether these requirements can be re-organized into something that does fit into the Task or Service model, as if this can be done the resulting code structure is often much cleaner and easier to manage. There are certainly cases where this is not the case, however, in which case using a Thread and Platform.runLater() is appropriate.
One last comment on polling (or any other requirement for a periodically-scheduled background task). The Service class looks like a good candidate for this, but it turns out to be quite hard to manage the periodicity effectively. JavaFX 8 introduced a ScheduledService class which takes care of this functionality quite nicely, and also adds handling for cases such as repeated failure of the background task.
This question already has answers here:
Handler vs AsyncTask vs Thread [closed]
(13 answers)
Closed 8 years ago.
I know this Question has been asked many times but all answers I got wasn't clear for Me.
I want to implement a File deletion process. I discovered that to do this kind of work it's recommended to run all the process in a separated thread.
For that, I can use AsyncTask, Handler and Thread. AsyncTask seems to be a good solution. However, AsyncTask is designed for small task. (When i try to delete a file whose length is more than 1G, AsyncTask crashes or doesn't execute onPostExecute.
Others thread handlers (Thread, Runnable...) can't manage UI (Update UI or show progress).
My Question is What is the good thread handler for Long tasks and How to manage UI with it.
First of all, if you need to perform work outside your main thread, but only while the user is interacting with your app, then you should create a new thread, otherwise use a Service.
Now, everything you can do with AsyncTask, you can also do it with a Thread(+ Handler). But the AsyncTask makes the developer job easier, because it is designed to communicate a worker thread with the main thread(caller thread). Now, if you use a Hanlder you can also communicate a worker thread with a caller thread(Note that the caller thread is not necessarily the main thread, it could be communication between two worker threads), if the caller thread is the main thread, you better use AsyncTask.
As far as i know, it goes something like this:
Use AsyncTask if you need to run a short task communicating with the UI thread
Use a Thread and Handler to run longer tasks that requires communication between the worker thread and the main thread(caller thread)
Use Thread, Handler and Looper (or HandlerThread, which is class for starting a thread that already has a Looper) for longer tasks that require communication between the worker thread and the caller thread(not the main thread).
Use IntentService for longer task that does not requires user interaction and needs only one worker thread.
The best for me, is the Asynctask, because the structure is well defined, you can know when is running the thread and when show the result.
http://masl.cis.gvsu.edu/2010/04/05/android-code-sample-asynchronous-http-connections/
Good article on using handlers above.
To delete using handler:
Create a runnable that does three things:
Delete file
Obtain msg and send on success
Obtain msg and send on failure
Using some framework to manage threads or using concurrency package, post the runnable and it will do the file Del off main thread. Handler callback will be msg success or msg fail that will process on main thread wherview controller.
Check out Needle and you can forget Handlers and AsyncTasks. Needle is an open-source, simple but powerful multithreading library for Android. With it you can say things like:
Needle.onMainThread().execute(new Runnable() {
#Override
public void run() {
// e.g. change one of the views
}
});
or
Needle.onBackgroundThread().execute(new UiRelatedTask<Integer>() {
#Override
protected Integer doWork() {
int result = 1+2;
return result;
}
#Override
protected void thenDoUiRelatedWork(Integer result) {
mSomeTextView.setText("result: " + result);
}
});
very simple API
fixed thread pool size
customizable thread pool size
supports UI interaction ("do work and then use result on UI thread")
android 1.5+
behaves the same on all platform versions
Check it out on GitHub: https://github.com/ZsoltSafrany/needle
I read probably every tutorial and every forum discussion on that subject but still can't make it happen! and it is very frustrating.
it seems that the way to do it is to use executeOnExecutor() method with - AsyncTask.THREAD_POOL_EXECUTOR, and so i did in my code. but still,the second task only beeing executed only after the first one has finished and not in the same time.
My min sdk version is 2.3 and the maximum is 4.2, so i did the check:
if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.HONEYCOMB) {
engine.setEnginesTurn(true);
engineThread = new EngineThread(board,engine,activity,boardView);
rt = new RotateTask(boardView);
engineThread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
rt.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else{
engine.setEnginesTurn(true);
engineThread = new EngineThread(board,engine,activity,boardView);
rt = new RotateTask(boardView);
engineThread.execute();
rt.execute();
}
Ignore the boolean variable here..it is not relevant,and also the other code since you wondered why i didn't post it. it is a mess but all working just fine,execpt for the execution of the two tasks. what am i doing wrong?
The reason i want the two tasks running parallely is: the first tasks is a computation task and the other one is a custom Hourglass image rotating animation while the computer is thinking (Its a game app).
EDIT: Ah.. and just wanted to include that i don't do the animation on the main UI thread is because i use sleep() for the animation ,so can't freeze the main thread.
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
So for parallel execution you can't use asynctask. The above is quoted from the doc. So for parallel execution i suggest you look at executor.
http://developer.android.com/reference/java/util/concurrent/Executor.html
It sounds like you are modifying the UI from the background thread in your AsyncTask. This is not thread safe and is probably causing the problem.
Keep your computation task on a separate thread and move your animation back onto the UI thread and (unless I am missing something) that should do the trick. Remember that anything that is drawn to the screen must be published on the main UI thread.
Just too much text. Please remove, there is a lot that is not needed.
Your design is complex, simplify it.
Why dont you just start 2 Async Tasks. Why have 2 jobs in 1 async task ? In one async task you can do your background thingy, and the other async task in the Pre and Post you can start your animation and stop your animation.