How to use FutureTask<V>, waiting for ui event? - java

I have an interface method which is supposed to return a Future object.
Future<Result> doSomething()
The implementation of this method shows some ui (javafx).
One of the ui elements has a listener, that needs to be called in order to receive the actual result, I need.
How do I achieve this?
Is there a better solution?
Here an example action I need to wait for:
// this is some framework method I cannot change
#Override
public Data execute(Data data) {
Future<Data> dataFuture = handler.doSomething(data);
// this should basically wait until the user clicked a button
return dataFuture.get();
}
// handler implementation
public Future<Data> doSomething(Data data) {
// the question is how to implement this part, to be able to
// return a future object
Button button = new Button("Wait until click");
// create thread that waits for the button click ?!????
// modify incoming data object when the button was clicked
// somehow create the Future object that's bound to the button click
return future;
}
This is what I want to achieve:
my method doSomething shows a new scene(ui) with a button on it
and returns immedeately the future object
future.get() waits until the user pressed the button
limitations: it has to be done with no extra library and on >=Java7

Use a javafx.concurrent.Task. It derives from FutureTask. There are extensive examples in the linked javadoc on Task usage.
Oracle also provide a tutorial which discusses Task usage:
Concurrency in JavaFX
I think this is what you want, but I may have understood the question, if so, please edit the question a bit to clarify requirements (perhaps with an mcve). The bit that makes me a little unsure is the part in your title "waiting for ui event?", I'm not quite sure what that means in this context.

This is a solution I was searching for. It's not very nice, since the Thread.sleep doesn't convince me.
but now you propably get an idea of what I want to achieve
// make sure this is not called on the ui thread
public Future<Data> doSomething(Data data) {
WaitingFuture future = new WaitingFuture(data);
Platform.runLater(() -> {
Button button = new Button("Wait until click");
button.setOnAction(future);
// show button on ui...
});
favouriteExecutorService.submit(future);
return future;
}
static class WaitingFuture extends Task<Data> implements EventHandler<ActionEvent> {
private Data data;
WaitingFuture(Data originalData) {
this.data = originalData;
}
private Data waitingData;
#Override
public void handle(ActionEvent event) {
waitingData = data.modify();
}
#Override
protected Data call() throws Exception {
while (waitingData == null) {
Thread.sleep(100);
}
return waitingData;
}
}

Related

how to take value outside jbutton actionlistener?

how to access value from outside the actionlistener
jbtnOne.addActionListener(new ActionListener() {
private String ana_data;
#SuppressWarnings("override")
public void actionPerformed(ActionEvent le) {
ana_data=jtf.getText();
}
});
pos_pred=def_pred(f_path,ana_data,prob_p,poslen,pcount);
neg_pred=def_pred(f_path1,ana_data,prob_n,neglen,ncount);
I need to take the data from outside the ActionListener inside the method given after that? can someone please help me?
There is no way of doing that.
The reason is that the ActionListener is executed later in time when the rest of the method is already run.
So if you want to work with something that depends on the action listener you have to move it there (or in a method tat is called from the ActionListener .
One of possible general patterns to tackle problems where some part of your code depends on values from code executed asynchronously is to use promises (CompletableFuture in Java). Generally it is advisable to design your overall code asynchronously in such situations, so that the method producing the value and the method requiring the value can both proceed at some even at some later point in time. From you question it is not clear if you can design it that way in your case. So I will assume you cannot. If your caller cannot behave asynchronously and needs the result of an asynchronous operation within a synchronous flow, then you will need to block the thread waiting for the result:
CompletableFuture<String> anaDataPromise = new CompletableFuture<>();
jbtnOne.addActionListener(new ActionListener() {
#SuppressWarnings("override")
public void actionPerformed(ActionEvent le) {
anaDataPromise.complete(jtf.getText());
}
});
anaData = anaDataPromise.get(); // will block until action performed
// anaData = anaDataPromise.get(10, TimeUnit.MINUTE); // will block until action performed or for max of 10 minutes
If you could permit the code that needs the anaData value to be fully asynchronous, then you could write it in a non-blocking fashion:
CompletableFuture<String> anaDataPromise = new CompletableFuture<>();
jbtnOne.addActionListener(new ActionListener() {
#SuppressWarnings("override")
public void actionPerformed(ActionEvent le) {
anaDataPromise.complete(jtf.getText());
}
});
anaDataPromise.whenComplete((anaData, throwable) -> {
if (throwable != null) {
throw new RuntimeException(throwable);
}
// do something with anaData value
});
// this point is reached immediately as the above code simply declares
// the action that will run later, the actions themselves are not yet run

Updating JavaFX ProgressIndicator multiple times from a Thread

I am working on the design of a multi-threading app in Javafx and would like to have a TableView with columns for Name and Progress of each Thread. After doing much research I found a similar example of what I am trying to accomplish here:
JavaFX Update progressbar in tableview from Task
(Which points to this: 'https://community.oracle.com/message/10999916')
The problem I am running into, however, is illustrated well in this example; how can you call a 'Task' object multiple times to update a ProgressIndicator?
My understanding from Oracle's documentation is that a Task object "is a one-shot class and cannot be reused". It would seem then that one can only invoke the call() method of a Task object once. I need to update the Task multiple times as it progresses through a Thread class, not call it once and arbitrarily increment through a For loop.
I have read about binding to Listeners and creating Service classes, but I am unsure if those are actual resolutions to this problem. I would therefore like to ask if this is even possible in Javafx, or if perhaps I am overlooking something. In the event someone has accomplished this in the past, it would be tremendously helpful if you might be able to illustrate how through the example provided previously.
Any direction on this would be appreciated, thank you.
-Drew
EDIT 1: I edited my wording as it was inaccurate.
EDIT 2: Here is an example with some pseudo code. Say I had a class with the following code:
public static class TaskEx extends Task<Void>{
#Override
protected Void call(){
updateProgress(.5, 1);
return null
}
public static void callThread() {
TableView<TaskEx> table = new TableView<TaskEx>();
//Some code for data in table.
TableColumn progressColumn = new TableColumn ("Progress");
progressColumn.setCellValueFactory(new PropertyValueFactor("progress");
table.setItems(<data>);
table.getColumns();addAll(progressColumn);
ExecutorService executor = Executors.newFixedThreadPool(<SomeNumber>);
for(TaskEx task : table.getItems(){
Threading.ThreadClass newThread = new Threading.ThreadClass(task);
executor.submit(newThread, <uniqueID>);
}
}
Then say I had a second class for Threading with this logic:
static class ThreadClass extends Thread{
Task progressTask;
public ThreadClass(Task task, Integer id){
progressTask = task;
}
public void run(){
ExecutorService executor = Executors.newFixedThreadPool(<someNumber>);
//This invokes the Task call for the correct progressIndicator in the Tableview.
//It will correctly set the progressIndicator to 50% done.
executor.submit(progressTask);
/* Main logic of the Threading class that involves the 'id' passed in. */
//This will do nothing because you cannot invoke the Task call more than once.
executor.submit(progressTask);
}
}
That is the sort of workflow I need, but I'm unsure how to accomplish this.
It seems like you don't get what we were talking about. You are trying to do your logic in the Thread.run(), and then each thread is creating a Task just to do the update of progress.
What you need is really to shift your logic from Thread.run() to Task.call(). Your thread is really just a thread, and all it does is to run a Runnable object (which is the Task).
public class TaskEx extends Task<Void> {
#Override
protected Void call() {
// Do whatever you need this thread to do
updateProgress(0.5, 1);
// Do the rest
updateProgress(1, 1);
}
}
public static void callThread() {
TableView<TaskEx> table = new TableView<TaskEx>();
ObservableList<TaskEx> data = FXCollections.observableArrayList<>();
data.add(new TaskEx()); // Add the data you need
TableColumn progressColumn = new TableColumn("Progress");
progressColumn.setCellValueFactory(new PropertyValueFactory("progress"));
progressColumn.setCellFactory(column -> {
return new TableCell<TaskEx, Double> {
private final ProgressBar bp = new ProgressBar();
#Override
public void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
}
else {
bp.setProgress(item.doubleValue());
setGraphic(bp);
}
}
}
});
table.setItems(data);
table.getColumns().add(progressColumn);
ExecutorService executor = Executors.newFixedThreadPool(data.size());
for (TaskEx task : table.getItems()) {
executor.submit(task);
}
}
This implement removes ThreadClass because there should not be any logic that must be done at a thread sub-class. If you really need to access the thread object as part of your logic, call Thread.getCurrentThread() from your TaskEx.call().
This implement also opens multiple threads doing exactly the same thing (which is quite meaningless). If you need to do a set of different logics, you can either make a set of different Task subclasses, or add a constructor taking in Runnable objects in TaskEx.
E.g.
public class TaskEx extends Task<Void> {
private final Runnable[] logics;
public TaskEx(Runnable[] logics) {
this.logics = logics;
}
#Override
protected Void call() {
for (int i = 0; i < logics.length; i++) {
logics[i].run();
updateProgress(i, logics.length);
}
}
}

How does calling Snackbar.make() from non-UI thread work?

I can call Snackbar.make() from a background thread without any problems. This is surprising to me since I thought UI operations are only allowed from the UI thread. But that is definitely not the case here.
What exactly makes Snackbar.make() different? Why doesn't this cause exceptions like any other UI component when you modify it from a background thread?
First of all: make() doesn't perform any UI related operations, it just creates a new Snackbar instance. It is the call to show() which actually adds the Snackbar to the view hierarchy and performs other dangerous UI related tasks. However you can do that safely from any thread because it is implemented to schedule any show or hide operation on the UI thread regardless of which thread called show().
For a more detailed answer let's take a closer look at the behaviour in the source code of the Snackbar:
Let's start where it all begins, with your call to show():
public void show() {
SnackbarManager.getInstance().show(mDuration, mManagerCallback);
}
As you can see the call to show() gets an instance of the SnackbarManager and then passes the duration and a callback to it. The SnackbarManager is a singleton. Its the class which takes care of displaying, scheduling and managing a Snackbar. Now lets continue with the implementation of show() on the SnackbarManager:
public void show(int duration, Callback callback) {
synchronized (mLock) {
if (isCurrentSnackbarLocked(callback)) {
// Means that the callback is already in the queue. We'll just update the duration
mCurrentSnackbar.duration = duration;
// If this is the Snackbar currently being shown, call re-schedule it's
// timeout
mHandler.removeCallbacksAndMessages(mCurrentSnackbar);
scheduleTimeoutLocked(mCurrentSnackbar);
return;
} else if (isNextSnackbarLocked(callback)) {
// We'll just update the duration
mNextSnackbar.duration = duration;
} else {
// Else, we need to create a new record and queue it
mNextSnackbar = new SnackbarRecord(duration, callback);
}
if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar,
Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) {
// If we currently have a Snackbar, try and cancel it and wait in line
return;
} else {
// Clear out the current snackbar
mCurrentSnackbar = null;
// Otherwise, just show it now
showNextSnackbarLocked();
}
}
}
Now this method call is a little more complicated. I am not going to explain in detail what's going on here, but in general the synchronized block around this ensures thread safety of calls to show().
Inside the synchronized block the manager takes care of dismissing currently shown Snackbars updating durations or rescheduling if you show() the same one twice and of course creating new Snackbars. For each Snackbar a SnackbarRecord is created which contains the two parameters originally passed to the SnackbarManager, the duration and the callback:
mNextSnackbar = new SnackbarRecord(duration, callback);
In the above method call this happens in the middle, in the else statement of the first if.
However the only really important part - at least for this answer - is right down at the bottom, the call to showNextSnackbarLocked(). This where the magic happens and the next Snackbar is queued - at least sort of.
This is the source code of showNextSnackbarLocked():
private void showNextSnackbarLocked() {
if (mNextSnackbar != null) {
mCurrentSnackbar = mNextSnackbar;
mNextSnackbar = null;
final Callback callback = mCurrentSnackbar.callback.get();
if (callback != null) {
callback.show();
} else {
// The callback doesn't exist any more, clear out the Snackbar
mCurrentSnackbar = null;
}
}
}
As you can see first we check if a Snackbar is queued by checking if mNextSnackbar is not null. If it isn't we set the SnackbarRecord as the current Snackbar and retrieve the callback from the record. Now something kind of round about happens, after a trivial null check to see if the callback is valid we call show() on the callback, which is implemented in the Snackbar class - not in the SnackbarManager - to actually show the Snackbar on the screen.
At first this might seem weird, however it makes a lot of sense. The SnackbarManager is just responsible for tracking the state of Snackbars and coordinating them, it doesn't care how a Snackbar looks, how it is displayed or what it even is, it just calls the show() method on the right callback at the right moment to tell the Snackbar to show itself.
Let's rewind for a moment, up until now we never left the background thread. The synchronized block in the show() method of the SnackbarManager ensured that no other Thread can interfere with everything we did, but what schedules the show and dismiss events on the main Thread is still missing. That however is going to change right now when we look at the implementation of the callback in the Snackbar class:
private final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {
#Override
public void show() {
sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, Snackbar.this));
}
#Override
public void dismiss(int event) {
sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, event, 0, Snackbar.this));
}
};
So in the callback a message is send to a static handler, either MSG_SHOW to show the Snackbar or MSG_DISMISS to hide it again. The Snackbar itself is attached to the message as payload. Now we are almost done as soon as we look at the declaration of that static handler:
private static final Handler sHandler;
private static final int MSG_SHOW = 0;
private static final int MSG_DISMISS = 1;
static {
sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
#Override
public boolean handleMessage(Message message) {
switch (message.what) {
case MSG_SHOW:
((Snackbar) message.obj).showView();
return true;
case MSG_DISMISS:
((Snackbar) message.obj).hideView(message.arg1);
return true;
}
return false;
}
});
}
So this handler runs on the UI thread since it is created using the UI looper (as indicated by Looper.getMainLooper()). The payload of the message - the Snackbar - is casted and then depending on the type of the message either showView() or hideView() is called on the Snackbar. Both of these methods are now executed on the UI thread!
The implementation of both of these is kind of complicated, so I won't go into detail of what exactly happens in each of them. However it should be obvious that these methods take care of adding the View to the view hierarchy, animating it when it appears and disappears, dealing with CoordinatorLayout.Behaviours and other stuff regarding the UI.
If you have any other questions feel free to ask.
Scrolling through my answer I realize that this turned out way longer than it was supposed to be, however when I see source code like this I can't help myself! I hope you appreciate a long in depth answer, or maybe I might have just wasted a few minutes of my time!
Snackbar.make is completely safe from being called form non-ui thread. It uses an handler inside its manager which operates on the main looper thread and thus hides the caller form the underlying complexities of it.
Only the original thread that created a view hierarchy can touch its views.
If you use the onPostExecute you'll be able to access the views
protected void onPostExecute(Object object) { .. }

Why does a callback method needs to return something? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have never before seen such a thing, so let's say I have such listener object:
MyWhateverListener dafuqListener = new MyWhateverListener() {
#Override
public void onSuccessCall(String s) {
// success call
}
#Override
public void onFailCall(boolean b) {
// fail call
}
#Override
public boolean onDafuqCall(int i, boolean b) {
// some whatever code
return false;
}
};
Everything fine, the appropriate method will be called back to, when some action succeedes, but what's with this return inside onDafuqCall method, why is it needed, where it will return something?
P.S. This interface is from an Android ads provider's SDK.
This is really quite a normal thing. A listener/observer interface is paired with a subject/event throwing class. Often you want your listeners to be totally disconnected from the behaviour of the subject, to the extent that the subject neither knows nor cares about how many listeners are registered. This is the 'pure' pattern. And this is the most common and it makes sense for all the methods to be void, since they are called only by the subject and the subjects behaviour does not depend on its listeners.
However, sometimes it makes sense for a listener to have other methods not intended to be called by the subject, and for the listener to act as a bridge between the state of the subject and some other part of the program. One common example is making special listeners for debugging. Here you make a new listener which extends your previous listener but it also keeps track of exactly when it is called by a subject, it then has a method with a return value so that your testing code can access this state, and see exactly what that listener was doing.
Finally, it occasionally makes sense to have listeners which affect the behaviour of the subject. In this case return methods are necessary. But this is rare and not without danger, it is sometimes used e.g. to make sure that things are deleted in a chain in the right order. So you stop the chain of deletes if you failed to delete a child. It has a name, but I cannot remember exactly what this pattern is called right now.
It is quite unclear what you ask but I'll give it a shot.
Interfaces are a way to allow objects to follow a specific pattern. They come handy, for instance, when I have an interface called "Listener" and five implementations:
ActionListener, MouseListener, KeyListener, CloseListener, StateChangeListener.
If I want to have a method allowing the user to register a user, instead of having to make separate "registerListener" methods for each implementation I can have: registerListener(Listener l).
Now back to your post, Interfaces may contain methods with return values, as an example if I have an interface called Event, and it contains a method called isCanceled() that returns boolean, then if I have an implementation called "ClickEvent" and I want to check if this event (after it has been called) is canceled by anyone or anything I'll invoke the isCanceled() method and that should return a value, because it is handled by the implementing object.
So to wrap this up, the return value is needed by the piece of code that calls the listener to get information. If we look in Java interfaces and their implementations we can find a ton of examples. You can check for yourself by looking into the java.uti.List interface source and an implementation like java.util.ArrayList
More information can be obtained from the Docs:
https://docs.oracle.com/javase/tutorial/java/concepts/interface.html
https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html
EDIT #1: Here is the example explained above, represented in code:
The event interface:
package com.fillpant.examples;
public interface Event {
public boolean isCanceled();
public void setCanceled(boolean value);
}
The ClickEvent (that implements Event):
package com.fillpant.examples;
public class ClickEvent implements Event {
private boolean canceled = false;
#Override
public boolean isCanceled() {
return canceled;
}
#Override
public void setCanceled(boolean value) {
canceled = value;
}
}
The place where ClickEvent is called. Here I demonstrate why the return value is needed (See the isCanceled() method):
package com.fillpant.examples;
public class EventCaller {
//This class calls an event, and all the listeners will have to handle it;
public void callClickEvent(){
Event e = new ClickEvent();
for(Listener l : all_registered_listeners){//this is hypothetical, if we had listeners.
l.event(e);
}
if(e.isCanceled()) return;
else{
//DoStuff
}
}
}
If you have any question don't hesitate to ask :D
This is my understanding about the topic:
Generally Listener/call-back methods don't need to return anything and they are called in response to an event.
e.g. onClick() method of OnClickListener.
OnClickListener onClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
//some click handling code
}
};
But if they are part of an event-chain then a boolean return type is used to either abort of continue the execution of events. e.g. onDrag() method from OnDragListener.
OnDragListener onDragListener = new OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
//some drag handling code
return false;
}
}
Documentation of this method says "return true if the drag event was handled successfully, or false if the drag event was not handled. Note that false will trigger the View to call its onDragEvent() handler."
so it is not very uncommon to have return in call-back/event-handling methods if they are part of chain of events. And what should be returned is part of the documentation of the API.

How to optimize my code to handle this special event

My program listens to 3 types of events: ADD, DELETE, REFRESH which is triggered by a 3rd party library component on UI. My listener looks like this:
//the timestamp is the time when the event occurs
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
//handle ADD event
}else if(event.getName().equals("DELETE")){
//handle DELETE event
}else if(event.getName().equals("REFRESH")){
//handle REFRESH event
}
}
The code works fine for each event, except a little problem with REFRESH event:
when refresh happened on UI, the 3rd party lib component fires consecutive 3 events in a short time, that's: ADD->DELETE->REFRESH, in this case my listener thinks there are 3 events, but actually it is only a refresh action on UI.
How can I optimise my code so that when ADD->DELETE->REFRESH happens consecutively very quickly, my listener could be smart enough to know it is only a REFRESH?
(ADD and DELETE events are NOT instances of the REFRESH event)
As I already said in the comments, the piece of code I posted below is working(tested). You will probably need some tweaking of the REFRESH_TIMEOUT and probably make it thread-safe, but I've tested the basic idea:
"If ADD event comes, create a timer for it. When DELETE comes, check if there is a timertask already. If it's not-> process DELETE. If there is -> process REFRESH. If the timer expires-> process ADD"
It's a bit of a hack, but with the information you gave, I think this solution may be the easiest thing to do. You may get into a problems if the proper events are coming faster then is your REFRESH_TIMEOUT. In that case, the logic will get a bit more complicated.
long REFRESH_TIMEOUT=100;
Timer timer = null;
MyTask myTask = null;
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
timer = new Timer();
timer.schedule(myTask = new MyTask(event), REFRESH_TIMEOUT);
}
if(event.getName().equals("DELETE")){
if (myTask!=null && !myTask.expired){
processRefresh(event);
timer.cancel();
}else{
processDelete(event);
}
}
}
private static class MyTask extends TimerTask {
Event event;
boolean expired;
public MyTask(Event event){
this.event=event;
}
#Override
public void run() {
expired=true;
processAdd(event);
}
}
private void processAdd(Event e){
...
}
private void processDelete(Event e){
...
}
private void processRefrsh(Event e){
...
}
After some thinking, I came up with my own solution:
That's in ADD & DELETE condition, I use Thread.sleep(1000), then get the system time, after which I compare the latest system time get in REFRESH condition, if the difference is within 1sec, then it is a refresh event.
private long timeout = 1000;
private long addEventTime;
private long deleteEventTime;
private long refreshEventTime;
public void listenToEvent(Event event, long timestamp){
if(event.getName().equals("ADD")){
Thread.sleep(timeout);
addEventTime = System.currentTimeMillis();
if((refreshEventTime - addEventTime) >timout){
//handle ADD event
}
}else if(event.getName().equals("DELETE")){
Thread.sleep(timeout);
deleteEventTime = System.currentTimeMillis();
if((refreshEventTime - deleteEventTime) >timout){
//handle DELETE event
}
}else if(event.getName().equals("REFRESH")){
refreshEventTime = System.currentTimeMillis();
//handle REFRESH event
}
}
Any guru has any comment on my solution ?
If the event api is well thought imo, I'd think that an ADD event could be an instance of a REFRESH event.
An example of this would be:
//AccidentAPI provided by FooBar Corp.
public CarAccidentEvent extends AccidentEvent {
private String carMake;
public String getMake() {
return carMake;
}
}
So, your listener would be able to do something like this:
public void listenToAccidents(AccidentEvent e) {
if (e instanceOf CarAccidentEvent) {
doStuff();
} else if (e instanceOf SkyJumpingEvent) {
doOtherStuff();
} else {
blah();
}
}
But again, this is going on the assumption that the ADD and DELETE events are instances of the REFRESH event. Though, perhaps their documentation would reveal something further about the EventAPI that may help answer the problem better.
Otherwise, you could add three attributes for the listener for the System's time in Millis which if the time in Millis is a difference greater than say 1ms, then process it, otherwise, go to the REFRESH case.

Categories