I'm making an Android game, and I'll need a continuously running thread for basically everything.
Now, however, I'm making the main menu (I always start simple, I'm new to coding), and I want an image to float across the main screen. I know how I could code that (determining the starting location, changing it), but I don't know how to run such a piece of code continuously (outside the UI thread).
P.S.: Please be easy on me. I know I'm probably missing something obvious, but I have virtually no Java experience at all.
1. Create a Non-UI thread, with Handler. And run it within Controlled loop using a boolean variable. Handler will be helpful in putting the output of the Non-Ui thread on the
Ui thread.
2. You can use an AsyncTask, introduced in android to synchronize the UI with Non-Ui thread.
while(check){//your code}
In run method you can put put a globle boolean variable to check the condition.
Related
I have to update a TextView from another class (not a activity) with the result from a method which can be slow to finish its search. While the method don't finish I thought set the TextView text to something like "loading..." and finally, after method result is ok, set the text to that result. Currently I'm doing something like this:
textView.setText("loading...");
Search s = searcher.search();
textView.setText(s.result);
Firstly, this still freezes the application until result is ok, once didn't not used new Threads. I know that to set content to Android widgets we have to do it inside the uiThread, but I don't know how to do it in my case, once I'm not inside a Activity.
In second place, that approach are not showing the "loading..." text. When I call that code the application just freezes and back with the final text.
Then, how to avoid that freeze/breaking until content is ok?
Do not do heavy operation inside MainThread (UI) in Android. For your case take a look to AsyncTask. It give you a method doInBackground where you should make some background stuff (http request, file i/o) then you will get call onPostExecute, that method will called on UI Thread with the results of doInBackground method. Another example.
I think the main thing to understand is that only UI specific tasks should run on the UI thread. If it is not UI related then it should run on another thread ideally as an AsyncTask.
Performing a search, generally speaking, is very performance heavy as you have pointed out. This will block the UI thread from updating the UI which will lead to unresponsive UIs and users may perceive this a crash or a slow app.
So firstly, to run the updating on the UI Thread.
runOnUiThread(() ->{textView.setText("loading...");});
then perform the search on a different thread
then once the search is finished update the UI using the same method as above
I read a lot about threads but don't understand yet :( let me explain to you what I have learned about threads. all we are working on such as codes any thing worked on UI thread or Main thread right? After that what happens if we call runOnUiThread? and my other question how do we know it's Time to use a new thread? I mean how do we understand we are working on another thread or replace or code in the new thread?
I know this is an unclear question but I don't understand as well. Please help me Thanks, john.
Let me try to answer. Actually Android has Main Thread (also called as UI Thread) and other thread.
Main Thread is basically for showing UI and other thread is for processing other big processes such as connecting to the server, etc.
runOnUiThread is called when you want to move from other thread to main thread. It is needed since only main thread can show/display result on UI. So when you have done some process on other thread, and you want to display the result on the apps, you need to show it on main thread by calling runOnUiThread.
We working on other thread only if it is a big or lengthy process like taking data from the server, load data, etc. And we move from other thread to main thread whenever we want to show some UI result.
Easiest way is to use AsyncTask<> class. You'll need to override three functions.
doInBackGround(...) : The codes that gets executed in background thread.
onPreExecute(..) : code that gets executed before background thread
completes executing like displaying progress bars, etc.
onPostExecute(...): Code that gets executed after background thread
has completed running. Perform task like updating UI in here
One general rule of thumb is: Don't use multithreading if you don't need to. Multithreading is always error-prone, and in many situations there's no benefit. Basically, you start a new thread whenever you execute a lengthy operation (i.e. some extensive computation like image processing) that would block the main thread for some time, so the application would become unresponsive.
I'm building a game in Android, and I have two threads. One for my data, and one for my UI. Up to this point, it's been fairly straightforward, as the UI thread pulls data that updates from the main thread without a problem. The issue I'm running into, is that my UI thread pauses certain parts of the game(a countdown timer) while it runs a certain animation, and I need a way to start that countdown timer again in the data thread, once the animation has ended. I have some solutions I've been working up, but it all seems so convoluted.
Is there something like a listener or something evens simpler where I can indicate to my data thread that a specific animation has ended in my UI thread? I just can't seem to get it to work the way I want.
Here's a pseudo code version of what I'm doing:
Main
{
gamethread();
UIthread:
while(gameIsRunning)
{
UIthread.draw();
if(gamethread.startAnimationButtonIsPressed)
{
UIthread.startAnimation;
}
}
}
Basically, in this pseudo code example, I'd need a way to indicate to the gamethread to unpress the startanimation button, or toggle that boolean or whatever.
I have read a number of articles on the internet about when something should run in the EDT, and when it shouldn't. But I'm still not sure I understand, so I'd like to ask a few question about this:
What pieces of code are going to run by default inside the EDT?
What pieces of code are going to be run be default outside the
EDT?
When should I use InvokeLater() so something that by default would
run outside the EDT, will run inside it?
When should I prevent a piece of code from running (by default) inside the EDT, by creating a new thread and putting that code inside it?
Thanks
All the code executed by an event listener.
The code in your main method, the code executed inside a thread that you explicitely started, or that has been started by the usage of a Timer or SwingWorker.
When creating a Swing GUI in your main method. Or when you want to interact with a Swing component (or its model) from inside a background thread.
When this piece of code is blocking (like long IO) or is taking more than a few milliseconds to execute. All the code executed from inside the EDT prevent this thread from doing its main job: repainting the GUI and reacting to events.
First of all thank you so much for editing and formatting your question very well. It helps a lot when answering your question.
Also i have to admit i am not 100% sure about my answers, so guys: feel free to correct me if i am wrong.
Everything which changes your graphical user interface.
Not quite sure about that.
If you need to update your gui with the time intensive calculations.
For example if you want to show the numbers from 0to 100000000 in a
JLabel.
Everything which would block your gui from user interaction because
it takes a lot of time, for example some calculations with a lot
of datasets.. But you need to make sure to access values only from
one thread or to synchronize the threads with volatile and
synchronize...
I had a program I got some help from here(how do I make my program check the stock market value every hour[java]) and I have been reading about swing worker ever since. I still have not fixed the program as I reread the official doc like 3 times and I am still a bit confused. Here is what I think I understand and please correct me if I am wrong.
You use SwingWorker when you have a long background process, and you put the SwingWorker inside your action performed? Once you create your process if you want it to update the GUI you make it return a value and you get() the value from the SwingWorker done() method. I am confused "where" to initialize SwingWorker because I want to say its the action performed, but isn't that where SwingInvokeLater is involved? if that is the case than what is the difference between the two. I believe SwingInvokeLater and done() both update your GUI by being run on the EDT.
I feel lost just writing that all out, I feel like I am getting closer to understanding but for some reason it just wont click. I don't like the examples the official doc provides, I guess I just don't see the whole picture. The official doc said to initialize your GUI inside a SwingInvokeLater but I don't understand the difference between that and just initializing my GUI in main().
Your questions / my replies:
You use SwingWorker when you have a long background process, and you put the SwingWorker inside your action performed?
It can go inside of an ActionListener, yes. You create it and execute it where it is needed, no more, and no less.
Once you create your process if you want it to update the GUI you make it return a value and you get() the value from the SwingWorker done() method.
That's one way to update the GUI. You can also use the publish/process method pair to update the GUI with interim results. You can also use a PropertyChangeListener attached to a SwingWorker to update the GUI. No matter what, it's usually a good idea to call get() somewhere, even if nothing is returned, as this will allow your Swing GUI to become aware of any exceptions that might have been thrown during the running of your SwingWorker.
I am confused "where" to initialize SwingWorker because I want to say its the action performed, but isn't that where SwingInvokeLater is involved?
The SwingUtilities.invokeLater(...) is used to queue code onto the Swing event thread, the EDT. This is not necessary inside of an ActionListener because its code is already called on the Swing event thread.
if that is the case than what is the difference between the two.
They are completely different. Again, invokeLater(...) is to call code on the event thread, and a SwingWorker is for calling long-running code off of the event thread.
I believe SwingInvokeLater and done() both update your GUI by being run on the EDT.
Yes they both can.
The official doc said to initialize your GUI inside a SwingInvokeLater but I don't understand the difference between that and just initializing my GUI in main().
By using SwingUtilities.invokeLater(...) you guarantee that the code passed into it is run on the EDT, the Event Dispatch Thread. If you don't do this, you don't have this guarantee. While many Swing programs will run most of the time without doing this, they may (and do) sometimes fail if this care isn't taken.
Edit
So I guess I am heading in the right direction. If I have a process that checks a value every hour on a website, since its a short process(takes a second) will it be better to use invokeLater()?
You could use some type of timer for this, possibly a ScheduledExecutorService which would be run in the background of Swing, perhaps with a SwingWorker. Then the process would be called background to the Swing thread, and you can update the GUI via publish/process.
Does the entire block of code go inside invokeLater or just the updating the GUI part. I feel like the entire code should go inside invokeLater but someone told me just to update the GUI such as (text.setText()) inside invokeLater().
As mentioned, your GUI needs to start up inside of a Runnable that is passed into a call to invokeLater(...). As for while your program is running, if the background code is run using a SwingWorker then usually there is no need a call to invokeLater(...). That is one of the reasons for using a SwingWorker rather than a plain vanilla Thread.
Edit 2
You state:
one last question I just came across while testing..inside an action performed I made the buttonclick change textfield to say hi, then I put in a try catch for Thread.sleep(1000) then change textfield to say ho. How come the result only outputs ho? it doesnt show hi, I tested with numbers and can see the program locking up. I know using a thread will fix this but just wondering why it wont display the output if I put a sleep.
When you call Thread.sleep(...) you put the calling thread, here the Swing Event Dispatch Thread or EDT, to sleep. Since it is responsible for all Swing painting and user interaction, the whole application goes to sleep, and the GUI is unable to perform any updates until the sleep has completed. This is precisely why you must use a background thread to perform this sort of thing.