Update UI from parent class on different thread from secondary class - java

I have a parent class which builds my UI (basically just a text box at the moment). I have created a secondary class which creates a new thread and I need to be able to update the textbox on the parent class from the new thread. Everything I try throws errors. I'm assuming I need to create some kind of dispatcher but my background is C# and I'm not 100% familiar on how to do this in Java.
My latest iteration passes the object of the parent class to a static method in the secondary which ultimately creates the new thread by instantiating an object for the secondary class (which has the run() method inside). I have a constructor in the secondary object that expects the passed in object from the parent class which, when passed in, sets a property that I've decalred in my member section for the parent class. when I try to access that member in the run() method to update a textbox on the parent class, I get an error.
Essentially the secondary class looks something like this:
public class SecondaryClass extends Thread {
private ParentClass pc = null;
public SecondaryClass(ParentClass PC){
pc = PC;
}
public static void StartThread(ParentClass pC){
Thread thread = new SecondaryClass(pC);
thread.start();
}
public void run() {
pc.myTextBox.append("something");
}
}
I've also tried creating a public method on the parent class that accepts a string as it's only argument and calling that method from within run() on the secondary class and passing "somethign" there. The method on the parent class updates the same textbox but having problems there as well.
can anyone please provide some insight as to what I need to do to access UI elements across these threads?

you will need to use SwingWorker
Similar question answered on stackoverflow for J2ME:
Interacting with UI threads in Java/J2ME
Also read following:
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html
Check simple example here:
http://download.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
Hope this helps.

Related

RxJava: How to subscribe to the events of a different class

I have a question about how to conceptually create an Observer and link it to another class: I currently have a class called Simulation that is supposed to create TransactionCreated objects and publish them as events. Another class called TransactionReceiver is supposed to be an Observer of every event that is published by the Simulation class and work with them.
The main method is included in the Simulation class and starts by creating an event in a static context and publishing it which works. My question would be how I am supposed to connect the TransactionReceiver as an Observer and let it subscribe to those events by receiving them in a method and work with those received objects? Do I need to create another class that would include the main method and create a Simulation and TransactionReceiver object that are then linked together as Observable and Observer? How would that look like?
And if I would extend that system with several different classes would they all have to be linked together through one class that connects Observers and Observables?
Your app should only have one main method.
Conceptually, this should be where you do the initial setup of Simulation and TransactionReceiver, so perhaps you could move it to a separate class to help you visualise how things should work. You could try something like below:
class Application {
private Simulation simulation;
private TransactionReceiver transactionReceiver;
public Application() {
simulation = new Simulation(/* params here*/);
transactionReceiver = new TransactionReceiver(/*params here*/);
}
public void go() {
simulation.simulate().subscribe(transactionCreated -> transactionReceiver.doSomething(transactionCreated);
}
public static final main(String[] args) {
Application application = new Application();
application.go();
}
}
Eventually as you get more fluent you could think about adding a dependency-injection framework like Guice or Dagger.
This will help you with managing the dependencies of the classes that you need to use throughout your application.
So you would end up with a more simple Application - it would just set up the DI-framework and then you can use the classes how you want to.
UPDATE:
If you want to communicate between two different classes, you will need to use methods:
class Simulation {
public Observable<TransactionCreated> simulate() {
// use PublishSubject or whatever
}
}

JavaFX Event handling from a different class

I looked at the stackoverflow questiions that seem similar to my problem, but none were of any help.
Here is my problem:
For a project, I am making a JavaFX app that is in pure Java without FXML. I have two classes, a controller Controller class and a class containing gui stuff GUI.
Controller has a member variable of type GUI and I am trying to assign an event handler to one of the buttons in GUI but it doesn't seem to work. It only works when I try implementing the handler inside the GUI class, but I need it to work in Comtroller.
In the constructor of Controller is as follows:
this.view = view;
view.addSimpleHandler(new SimpleHandler());
view is of type GUI and addSimpleHandler is a member function of view
SimpleHandler is an inner class of Controller that implements EventHandler and overrides the handle() function
public void addSimpleHandler(EventHandler<ActionEvent> e) {
simpleButton.setOnAction(e);
}
here is my main method and class signature for GUI
public class GUI extends Application {
//member variables for the GUI design including simpleButton
private Button simpleButton;
public static void main(String[] args) {
GUI view = new GUI();
Controller controller = new Controller(view);
Application.launch(view.getClass(), args);
}
public GUI() {
simpleButton = new Button("Simple button");
//rest of code is setting up GUI into my panes
}
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(mainPane, sceneWidth, sceneHeight);
//mainPane is a pane that contains simpleButton with a screenwidth and screenHeight
primaryStage.setTitle("Simple");
primaryStage.setScene(scene);
primaryStage.show();
}
Don't instantiate your application class manually. To understand why, see the documentation regarding the JavaFX life-cycle (emphasis mine):
The entry point for JavaFX applications is the Application class. The JavaFX runtime does the following, in order, whenever an application is launched:
Starts the JavaFX runtime, if not already started (see Platform.startup(Runnable) for more information)
Constructs an instance of the specified Application class
Calls the init() method
Calls the start(javafx.stage.Stage) method
Waits for the application to finish, which happens when either of the following occur:
the application calls Platform.exit()
the last window has been closed and the implicitExit attribute on Platform is true
Calls the stop() method
As you can see, JavaFX itself will instantiate the application class and it's that instance which has its life-cycle methods invoked—those methods being init(), start(Stage), and stop(). However, in your code you have the following:
public static void main(String[] args) {
GUI view = new GUI(); // created your own instance
Controller controller = new Controller(view); // gave controller that instance
// Launches JavaFX which starts the life-cycle documented above
Application.launch(view.getClass(), args);
}
You create your own instance of GUI. This instance is not managed by JavaFX which means its start(Stage) method is never invoked. When you create the Controller instance and pass it your instance of GUI you're adding the EventHandler to a node which is never displayed. The window you see displayed is from the GUI instance created as part of the call to Application#launch and that GUI instance is never associated with a Controller.
For JavaFX applications you should consider the init() and start(Stage) methods as the entry points1. In other words, create the Controller in one of those aforementioned life-cycle methods. Although I suppose you could do the same in the constructor instead2. Whichever you choose, take note of which thread invoke each method, which is documented in the same place as the life-cycle. Here are the essentials:
The application class is loaded, initialized, and constructed on the JavaFX Application Thread.
The init() method is invoked by the JavaFX-Launcher thread.
The start(Stage) and stop() methods are invoked by the JavaFX Application Thread.
Remember that certain actions can only be executed on the JavaFX Application Thread.
1. You can still execute code before the call to Application#launch within the main method if needed. The only constraint is that code should not be directly related to JavaFX.
2. Your constructor is currently public and has zero parameters—keep it that way. JavaFX requires the application class to have a public, no-argument constructor in order to construct an instance via reflection.

Call() is not public in android.telecom.Call, Cannot be accessed from outside package

I have the next class within SDK23 which should support playDtmfTone() :
import android.telecom.Call;
public class myDtmf {
public void myPlayDtmfTone() {
Call mytone = new Call(); // error here for Call()
mytone.playDtmfTone('0');
}
}
The Call() in the line 'Call mytone = new Call()' shows the error:
Call() is not public in android.telecom.Call, Cannot be accessed from outside package.
How can I make Call() public or make it accessible ?
Thank you very much.
In this specific case, referring to the Javadoc of Call:
[Call] Represents an ongoing phone call that the in-call app should present to the user.
So it doesn't really make sense to "create" an instance of it, since that requires you actually to create an actual phone call to some endpoint.
In general, if a method is not accessible outside the package, you aren't supposed to access it - it is not part of the API that the class developer has provided. There are ways to access it - specifically, reflection - but this is hacky and it is massively unlikely to be the way that you are meant to use the class.
The class may provide you with some other means to create an instance, like a static factory method (or an external factory) - but, for the reasons outlined above, that doesn't make sense in this case either.

Get back to Android activity after background thread is complete

I'm using Parse with my Android app, and my code looks like this:
public class SignupActivity extends Activity {
//Collect signup data
User.signupInBackground(data);
}
public class User{
//User methods, constructors, etc
public static void signup(data){
ParseUser pUser = new ParseUser();
//Build data into pUser
pUser.signUpInBackground(new SignUpCallback() {
public void done(ParseException e){
if (e!=null){
Log.v("Signup",e.toString());
}
}
});
So the question is, how do I notify my activity when the signUpInBackground process is complete? I can't have SignupActivity implement SignUpCallback because it's an abstract class and I have to extend Activity.
Ultimately, what I'm trying to do is display a dialog box or waiting animation, and then get rid of it when the background thread is done. Alternatively, the background thread could launch an activity. The problem with this is that the User class and the anonymous inner class don't have their own Context, so they can't start activities.
I'm fairly new at this, so thanks for your help.
Several approaches might work given your current code structure.
Create a Handler in SignupActivity and pass that to the User so it has a way of interacting with the activity.
Make SignUpCallback an interface instead of an abstract class.
Create an instance of a concreate subclass of SignUpCallback in your SignupActivity class; it will have access to the methods of SignupActivity.
I'm assuming that signUpInBackground is executing on a worker thread and that the callback is invoked from that thread. If that's correct, then in all cases you will need to interact with SignupActivity through a Handler. Thus, I'd suggest method #1 unless the other approaches allow for cleaner code.

How to Stop running singleton class multiple times in play framework

I have a singleton class in my play app. This singleton class is a long process which will generate reports from DB which consumes huge amount of memory. When i run my application in dev mode this singleton functionality is executing several times. I want this functionality to run only once. What should I do for that?
My code is:
public class DataGridManagerImpl extends ComponentContainer implements DataGridManager {
private static DataGridManager instance = null;
private DataGridManagerImpl(){
load();
}}
#Override
public void load() {
//Myreports function
}
public static DataGridManager getInstance(){
if (instance == null){
instance = new DataGridServiceManagerImpl();
}
return instance;
}
}
In my controller file inside a template function
DataGridManager dataGridMgr = DataGridManagerImpl.getInstance();
If i access the page it is executing the load reports function again.
Without code explaining how did you create your class it's hard to answer. From what I understand what you want is to run a process only once.
Problably the best approach is to use a Scheduled Job. This will trigger the process at a certain time, and Play ensures that only 1 instance of this process is running at the same time, even if the schedule would indicate another instance has to run. Let's say you have a process scheduled every hour and the process takes 3 hours. The initial process will be the only one running for 3 hours until it finishes.
Now, I would assume you want your process to be recurring as it generate reports. If not, if you only want to run it once, then you may want to use an asynchronous bootstrap job instead. This would run just once, at the beginning of the application.
EDIT on update: during development the #OnApplicationStart may execute several times, as Play may automatically reload the application when you do certain code changes. This is part of the dev process (the same that an #OnApplicationStart job won't start in Dev until the server gets a request).
As it's a job that you only want to run once, you may try to skip it in dev mode using the check:
if(Play.mode == Play.Mode.DEV)
If you need to run it at least once, add a dev-only url that you can access during dev to start the process.
Now, on your update you also mention that you are calling that code in a controller, and that every time the controller is acessed the method is called. That's expected. Singleton doesn't mean that it will run only once, but that there is only 1 object in the system. If in your controller you launch the calculation, that will happen everytime you access the controller.
SECOND EDIT (on comments): Arasu, the other issue is that you are calling the method load() when you construct the object. A singleton doesn't garantee that the object will only be constructed once. It garantees that, once constructed, only 1 object will exist. But it may happen that the object is removed by GC, in this case as per your code if you construct it again then you'll call load() and redo the processing.
The best solution is to not call "load" on constructor, but to force the user (you) to call it after retrieving the instance. An alternative is to set some flag at the beginning of load that detects if the code has been run. Be aware that Play is stateless, so that flag will need to be stored in the database.
the defition of a singleton is that it can run only once, it's practically the nature of the pattern. If you somehow manage to run it multiple times, you might have implementation errors in your singleton.
Recheck the singleton pattern in Wikipedia.
Edit:
This code makes it impossible to fetch more than one instance. How would you get more than one?
public class Singleton {
private static Singleton _instance;
private Singleton() { }
public static synchronized Singleton getInstance() {
if (null == _instance) {
_instance = new Singleton();
}
return _instance;
}
}
Or do you mean that you instanciate the Singleton class, instead of calling Singleton.getInstance()?
It is possible to have a Singleton doing a time consuming processing and be called the same time by two different threads. I think this is the situation here. The same Singleton object's method is called multiple times from the program.
I have run a little test... two thread calling the same Singleton object and here is the result
Thread[Thread 1,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 2,5,main] internal loop number = 0 Object = example.Singeton#164f1d0d
Thread[Thread 1,5,main] internal loop number = 1 Object = example.Singeton#164f1d0d
and here is the code.
package example;
public class Singeton {
private static final Singeton INSTANCE = new Singeton();
private Singeton() {}
public static Singeton getInstance(){
return INSTANCE;
}
public boolean doTimeConsumingThing(){
for (int i=0; i<10000000;i++){
System.out.println(Thread.currentThread() + " internal loop number = " + i + " Object = " + toString());
}
return true;
}
}
package example;
public class MulThread extends Thread{
public MulThread(String name) {
super(name);
}
#Override
public void run() {
while(true){
Singeton s = Singeton.getInstance();
System.out.println("Thread " + getId());
s.doTimeConsumingThing();
}
}
public static void main(String[] args) {
MulThread m1 = new MulThread("Thread 1");
MulThread m2 = new MulThread("Thread 2");
m1.start();
m2.start();
}
}
Please correct my notion above if i am wrong.
Hence what you need is a variable to keep track of the state of the time consuming procedure (i.e. a boolean isRunning) or the times the procedure has been called.
You can also make the pertinent time consuming method of the Singleton synchronized so only one thread can access the method while it is running (in my example if you make the doTimeConsumingThing() synchronized, the second thread will block until the singleton's method called from the first thread is finished.
Hope it helps
I had the same problem in DEV mode, and what I did is create a module for the tasks I don't want to be run at every #OnApplicationStart.
The trick is to launch those tasks in a overriden "onLoad()" method, in the module:
public void onLoad()
{
// tasks to run one time only
}
The onLoad() method is called one time only, not each time the application is restarted.
I don't know if this will help, but here are some things to check:
The code in your question is not thread-safe. You're missing the synchronized keyword in getInstance. That could cause the constructor to be called more than once by different threads.
Could DataGridManagerImpl be getting loaded by different classloaders? That static instance variable isn't static for the whole JVM, just static for that class' classloader.
load is public. Could some other code being calling that method?

Categories

Resources