why in my code, the TextView does not take except the last count.
the result just is: counter= 4
int i =0;
while (i< 5) {
try {
Thread.sleep((i*1000));
mText.setText("counter"+ i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// mText does not show
mText.setText("counter= "+ i);
i = i +1;
}
You are blocking the UI thread when your app sleeps, so the screen is not redrawn, hence you don't see the text changes until your loop ends.
The UI thread
When an application is launched, the system creates a thread called
"main" for the application. The main thread, also called the UI
thread, is very important because it is in charge of dispatching the
events to the appropriate widgets, including drawing events. It is
also the thread where your application interacts with running
components of the Android UI toolkit.
For instance, if you touch the a button on screen, the UI thread
dispatches the touch event to the widget, which in turn sets its
pressed state and posts an invalidate request to the event queue. The
UI thread dequeues the request and notifies the widget to redraw
itself.
This single-thread model can yield poor performance unless your
application is implemented properly. Specifically, if everything is
happening in a single thread, performing long operations such as
network access or database queries on the UI thread will block the
whole user interface. No event can be dispatched, including drawing
events, while the long operation is underway. From the user's
perspective, the application appears hung. Even worse, if the UI
thread is blocked for more than a few seconds (about 5 seconds
currently) the user is presented with the infamous "application not
responding" (ANR) dialog.
If you want to see how bad this can look, write a simple application
with a button that invokes Thread.sleep(2000) in its OnClickListener.
The button will remain in its pressed state for about 2 seconds before
going back to its normal state. When this happens, it is very easy for
the user to perceive the application as slow.
To summarize, it's vital to the responsiveness of your application's
UI to keep the UI thread unblocked. If you have long operations to
perform, you should make sure to do them in extra threads (background
or worker threads).
More info:
http://developer.android.com/resources/articles/painless-threading.html
That is the problem. And AsyncTask is (one) solution:
AsyncTask
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a
background thread and whose result is published on the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
First, it would be a good idea to change the text before sleeping.
Second, if you do this in a separate thread, you have, nevertheless, to manipulate a widget in the ui thread. Try this :
instead of
mText.setText("counter"+ i);
try
runOnUIThread( new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
});
Regards,
Stéphane
"while (i <= 5)" will make it go on till five.
Another solution is to make "i" 1 to start with, instead of 0.
Does this help?
Use a for loop (inside a non-UI thread):
for (int i = 0; i < 5; i++}{
try {
Thread.sleep((i*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUIThread(new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
});
}
Many answers here gave you all the information you need to achieve what you want but it may be difficult to understand.
I will propose you below a new way to achieve it, maybe easier. But I want to underline that you should understand what people wrote, my previuos post and the one from #LAS_VEGAS at least.
Here is something easy : use a handler.
add a data member like
Handler handler = new Handler();
then on click :
for (int i = 0; i < 5; i++}{
handler.postDelayed( new Runnable() {
public void run() {
mText.setText("counter"+ i);
}
}, i * 1000 );
}
I don't have access to my very own computer right now and fear this may not compile due to a non final variable used inside a annonymous inner class. So you could also try to build a named inner class like this in your main java class :
public class ButtonTimerThread implements Runnable
{
privqte int i =0;
public ButtonTimerThread( int i)
{
this.i = i;
}//cons
public void run()
{
mText.setText("counter"+ i);
}//met
}//class
qnd then you click listener method would look like :
for (int i = 0; i < 5; i++}{
handler.postDelayed( new ButtonTimerThread( i ), i * 1000 );
}
As your handler will be created by the UI thread, it will be able to update UI. The handler offers the advantage to have a delay mechanism that doesn't block the UI thread that is reacting to your click action.
I hope this helps,
Stéphane
Generally, good solutions to problems with sleep() involve stopping using sleep(). Blocking the UI thread is always a very bad idea. It makes you application's UI non-responsive.
In your case you want an event to run every second. The correct way to implement that is with a timer.
Related
I am trying to understand how UI thread's event queue works. I'm trying to run a code that can be broken into many parts but unfortunately it must run on the UI thread. So, in order to not block the UI thread and receive a ANR I was wondering if I can break that code in many Runnable objects and run them using runOnUiThread from another thread.
My question is, will this block the UI thread? If, for example, I have a piece of code that definitely runs in over 5 seconds and I break this code into, let's say 1000 Runnable objects, and add them to the event queue of the UI thread, will other events get processed by the UI thread between them?
Edit: I think I found a better way to express myself in case the above explanation is confusing.
The 1000 Runnable objects was just an example, in actual code I want to have at most 10.
Basically, I want 10 Runnable objects, each one initialising an Ad network on the UI thread. I want these Runnable objects to run one after another, not in parallel. Also, I want the UI thread to be able to process other events between running these objects, so that I don't get an ANR in case running all 10 run methods will take more than 5 seconds.
NOTE: I don't know why initialising Ad networks must be done on the UI thread, but it must, otherwise the app crashes. It also states in some of the networks' sdks' documentation that initialisation must happen on the UI thread. This is why I need to run them one after another on UI thread and I can't run them in parallel in the background.
Also, the app is actually a OpenGl game, so calls to running the Runnable objects will be made from a GL thread, not the main thread, so they will be added to the event queue, and not executed immediately.
Well, Runnable inside your runOnUiThread is just operation in Main Thread.
Imagine that some simple action like
textView.setText("example");
will block Main Thread for 5 ms. Usually you will not see it.
Now imagine that you have like 1000 same operations for 5 seconds. And every blocks Main Thread for 5 ms. Simple calculating 5ms * 1000 = 5000ms = 5 seconds. So it will block Main Thread permamently. But if you have 10 operations you will block only 50 ms, in other words its just 1% of load that you will not feel.
So possible amount of calls depends on size of View, how hard render is and how fast is device.
P.S. For adepts of AsyncTask - there is no real difference between runOnUiThread and AsyncTask because those 1000 Runnables will execute in Main Thread by the same way.
Even if I do same thing inside onCreate method of Activity that will block UI hard
Yes. Runnable executing on UI thread will block main thread.
Check if below approach is useful for you.
Create a Handler with Looper from Main :requestHandler
Create a Handler with Looper for main thread : responseHandler and override handleMessage method
post a Runnable task on requestHandler
Inside Runnable task, call sendMessage on responseHandler
This sendMessage result invocation of handleMessage in responseHandler.
Get attributes from the Message and process it, update UI
Sample code:
/* Handler */
Handler requestHandler = new Handler(Looper.getMainLooper());
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Adwork task is completed:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
for ( int i=0; i<10; i++) {
// Start Adwork task
Runnable myRunnable = new Runnable() {
#Override
public void run() {
try {
/* Your business logic goes here */
// Send some result after computation
String text = "" + (++rId);
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
System.out.println(text.toString());
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
}
Useful articles:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
android-looper-handler-handlerthread-i
What you are looking for is an AsyncTask.
These are designed to do some background processing, while the UI thread continues. It will NOT block the UI and will NOT cause ANR.
Within the AsyncTask, is an onPostExecute method, which allows you to post results back to the UI. So it is not completely detached from the UI Thread. And an onProgressUpdate for connection during the background processing
Yes, you will feel animation will stop or start shutter if You run heavy operations in Ui thread. It's also depends of how fast device is.
What I would suggest you is to break your code in two parts. One that can be done in background and second that need Ui thread and execute them in AsyncTask.
Use doInBackgroud method to execute heavy operation and onPostExecute to update UI.
Note: If you break code into 1000 threads and run them in one moment, then probably You will hit device queue limit. (Break them into 10-50 parts. )
I have a JProgressBar and want to be able to see it dynamically updated. The progress bar should be able to visibly move from one position to another, not just change without the bar visibly changing (think regular loading bars).
public static void dropHPBar(int before, int after) {
Thread.currentThread.sleep(50);
while (before > after) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
GameMain.gW.setHP(before);
b --;
}
and from GameMain.gW:
public void setHP(int x) {
hpBar.setValue(x);
}
Why is the progress bar not being visibly updated?
Calling Thread.sleep in the EDT (event dispatch thread) prevents UI updates. You need to use Swing Worker in order to archive proper concurrency.
From the Oracle website:
Swing consists of three kinds of threads:
Initial threads, the threads that execute initial application code.
The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also
execute on this thread.
Worker threads, also known as background threads, where time-consuming background tasks are executed.
Tasks on the event dispatch thread must finish quickly; if they don't,
unhandled events back up and the user interface becomes unresponsive.
My project run on java swing there are 2 button (start/stop) for counting.
When I click start button. There is one thread running (Thread-0) ,then click stop button "Thread-0" disappear but when I click start button many times. there are many threads such as Thread-5, Thread-6, .. Thread-10 are running.
Problem :
If click start and then stop counting is ok. but click start many times it's incorrect counting.
start button
private void btnStartActionPerformed(java.awt.event.ActionEvent evt) {
start();
btnStart.setEnabled(false);
btnStop.setEnabled(true);
}
stop button
private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {
isEnable = false;
btnStop.setEnabled(false);
btnStart.setEnabled(true);
}
start() method :
isEnable = true;
Thread refreshPlan = new Thread() {
#Override
public void run() {
while(isEnable) {
try {
sleep(CYCLE_TIME * 1000);
PLAN += 1;
planValue.setText(String.valueOf(PLAN));
} catch (InterruptedException ex) {
//ignore
}
}
};
};
refreshPlan.start();
Can I run only single thread when click many times in start button ?
any suggestion? thanks.
sorry for my bad english.
There are four significant problems here:
Unless isEnable is declared as a volatile variable, there's no guarantee that a write from one thread will be seen in another thread
Likewise your access to the PLAN counter (which is badly named - please follow Java naming conventions) is unsafe. You may wish to consider using AtomicInteger for this.
You're making changes to the UI from your extra thread. You can't do that - in Swing (and most UIs) all access to UI components has to be done on the thread responsible for that UI. See the Swing concurrency tutorial for more details.
Because you only check isEnabled one per second, it would be possible to stop and start multiple threads in the meantime... leading to several threads being active at once. This could interfere with your counting.
You might find it's better to use a javax.swing.Timer which fires once a second, and just checks whether or not it's meant to do anything. That way everything can be on the UI thread.
start method is instantiating new Thread() that's why every time u click it, it brings new thread into life.
declare Thread refreshPlan class variable then in start method put all the code in this check
if(refreshPlan == null || !refreshPlan.isAlive()){
//ur existing code to instantiate new thread.
}
I am trying to get the GUI to update after each iteration of the loop. I have read other answers to similar questions and still can't get it to work. In the code below I call simulate which runs through the loop calling step which calculates and changes GUI components as needed but the GUI isn't updating until after the loop completely ends. How can I get it to update after each iteration?
public void step(View v) {
for (int i = 0; i < cells.length; i++)
update(i);
count++;
Toast.makeText(getApplicationContext(), count + "", 1000).show();
}
public void simulate(View v) {
while (!pause) {
step(v);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void update(final int i)
{
//This goes through each button and counts the neighbors (this is the
//intensive work
int neighbors = getNeighbors(i);
//With the information provided from the getNeighbors the following if
//statement updates the GUI using the dead and alive method calls.
if (isAlive(cells[i])) {
if (neighbors < 2)
dead(cells[i]);
else if (neighbors > 3)
dead(cells[i]);
}
else {
if (neighbors == 3)
alive(cells[i]);
}
}
The problem is that you are running that code in the main thread of your application. The GUI runs on the same thread and can not be updated while you are blocking it.
You have to do the calculations in a different task and then send a message to the main process to update the GUI.
Read this for background-information (if you are new to this, you have read the backgrounds first):
http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html
The easiest way to do this is to use AsyncTask and then do the GUI update with "onProgressUpdate()".
Although AsyncTask already makes things pretty easy, you have to mind that the underlying activity can be destroyed while AsyncTask is running. This is not really well covered in the documentation but I find that the use of Fragments is probably the best way of dealing with it. Read this article for a quite nice description:
http://blogactivity.wordpress.com/2011/09/01/proper-use-of-asynctask/
Remark: read also the AsyncTask documentation. I could not post the link due to restrictions of the forum.
We are always adviced that , UI work should be on the UI-Thread, and Non-UI work on Non-UI Thread, but from HoneyComb android version it became a LAW. When we start an application in Android, it start on the Dedicated UI thread, creating any other thread will drop you off the UI thread, you normally do this to do some process intensive work, but when you want to display the output of the non-ui thread process, on the ui thread then you will experience lagging, exception etc...
From my view this can be done in two ways....
Using Handler... Handler stores the reference of the thread on which it was created, Initialize Handler inside the onCreate() method, and then use handler.post() to update the UI thread.
Use AsyncTask<> provided by android, it synchronizes the UI and Non-UI threads
Methods in AsyncTask<>
doInBackground(String...) // Work on the Non-UI thread
postExecute(String result) // Getting the Output from the Non-Ui thread and
Putting the Output back on the UI Thread
I think you have to use AsyncTask for this.
Try to read the documentation..
http://developer.android.com/reference/android/os/AsyncTask.html
I have an app and want to put the main thread to sleep for 1500ms, so I can show a ProgressDialog, but I don't know how to do it. It's possible to stop an app main thread? I can achieve the same goal using another thread right?
Stopping the main thread is usually a bad idea as it would also stop all UI interaction processing.
Try making the progress dialog modal. This will prevent the user from doing anything on your UI until the dialog is gone. I think this will achieve what you want to do and is compatible with how Android works
not a good idea to do this, but if you have to use this
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
//handle
}
Don't stop main UI thread! It will freeze UI. I can imagine that you show progress dialog during some background operation. Once this operation is complete just post something to update UI via handler.
The point of progress dialog is to interact with user while something long is executing. Otherwise you would not even need background operation and progress dialog. You would just do you operation in main UI thread and wait for UI to unfreeze.
What you're asking for should be unnecessary and as Carsten said, is a bad idea. It's a cardinal rule that you both never interrupt the UI thread and also only update elements of the UI on that thread. While a Dialog and any of it's subclasses are shown, nothing in the background will receive any input, so while it's up... though the main thread is running, nothing should be happening besides what is going on in the Dialog.
What you're probably looking to do is use something like an AsyncTask() to show your ProgressDialog, do some work, then dismiss it when that work is done.
To do something like this, you'll want to use "Runnables" along with a "Handler." As others mentioned, you don't want to stop the main UI thread. Since there is only one, you won't be showing ANY updates if you make it sleep or wait. See a small sample below of running code on another thread.
The main thing to take out of this is that sleeping the main thread means stopping any and all visual updates.
// Class Variables
private Handler mHandler;
#Override
public void onCreate(){
// Create a Handler Object
// In Layman's terms, Handlers can run processes off the main
// User interface thread.
mHandler = new Handler();
// Post a "Runnable" after a delay in milliseconds
// On a separate thread, the progressDialog_Runnable
// will call the function "createProgressDialog"
mHandler.postDelayed(progressDialog_Runnable, 250);
}
// Runnables (Process to run on separate thread)
private Runnable progressDialog_Runnable;
{
progressDialog_Runnable = new Runnable(){
#Override
public void run() {
createProgressDialog();
}
};
}
// Method you create to make the progress dialog
private void createProgressDialog(){
//... Run this code on a separate thread via Runnable
}
Sleep 10s on a thread in Kotlin
try {
Thread.sleep(10000)
} catch (e: InterruptedException) {
//handle
}