Android update UI from another thread [duplicate] - android

This question already has an answer here:
Updating UI / runOnUiThread / final variables: How to write lean code that does UI updating when called from another Thread
(1 answer)
Closed 9 years ago.
Good day,
I want to update an image button in my UI from another thread. below is my code that i run in my mains threads onCreate() method.
new Thread(new Runnable() {
public void run() {
ImageButton btn = (ImageButton) findViewById(R.id.connected_icon);
if (netConnection.IsConnected()) {
// Change icon to green
btn.setImageResource(R.drawable.green_small);
} else {
// Change icon to red
btn.setImageResource(R.drawable.red_small);
}
try {
// Sleep for a second before re_checking.
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
No when i run this i gen an error int he LogCat saying i cannot update the UI from annother thread.
I remember reading soem where once that this is the case so that you don't get multiple threads updating the same UI object at once. But how can i achieve this. i am sure there is a work around?
Thanks

You cannot directly acces UI components from the thread.
The correct way to do this is by creating a handler
final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
}
};
And send messages to UIThread with
Message msg = new Message();
//TODO: add stuff to message
mHandler.sendMessage(msg);
inside your Thread.
This or use an AsyncTask instead and do the updates from inside of pre, post or progressUpdate methods

UI Elements should be updated only from the UI thread. Use an async task to do background word, and modify the UI in onPostExecute, which runs on the UI thread

Related

Why do we use a Handler? Why we don't call an interface element inside a Runnable object?

Whenever this code is executed the application crashes, but when a handler is used the application works as expected.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
//this code needs to be inside a Handler ??
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
//this code needs to be inside a Handler ??
}
};
Thread thread = new Thread(r);
thread.start();
}
Here all the answer have mentioned use of handler is used in Android with UI thread. But Let me add more to it.
If you have gone Android documentation/tutorial you would know that
When an application component starts and the application does not have
any other components running, the Android system starts a new Linux
process for the application with a single thread of execution. By
default, all components of the same application run in the same
process and thread (called the "main" thread or uiThread).
for more info refer
Now coming to your mentioned example; you have created another thread using Runnable...so there might be scenario you need thread(s) other then just mainThread in Android Application.
If you are good in JAVA Threading concept then you would know how Interthread communication happens and for different ways how it can be done refer
So coming back to question in android we have mainThread or uiThread so called which holds our ui i.e. view component. These component are private to mainThread so other thread cannot access it...which has been mentioned in previous answer. This is where Handler comes into picture you do not need to worry how your message would be passed from one thread to another.
Handler
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your
own.When posting or sending to a Handler, you can either allow the
item to be processed as soon as the message queue is ready to do so,
or specify a delay before it gets processed or absolute time for it to
be processed. The latter two allow you to implement timeouts, ticks,
and other timing-based behavior.
For more info refer docs AND
For more info with handler and UI thread
Code that deals with the UI should be run on the UI (main) thread.
You (probably) create a handler on the UI thread, so all messages sent via it will run on that thread too.
The Runnable is use for background process(background thread) and textview is in your UI thread so background thread can't communicate with foreground thread so it will gives you error and crashes your application.you can also use the runOnUiThread. example.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
try {
// code runs in a thread
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
};
Thread thread = new Thread(r);
thread.start();
The reason why your app crashes is that you modify View from a non-UI thread.
If you do it using a Handler that belongs to UI-thread this works as expected.Update
If you need to run Runnable to modify UI you may choose from:
1) yourActivity.runOnUiThread(Runnable r)
2) yourHandlerOnUIThread.post(Runnable r)
3) yourView.post(Runnable r)

Android - efficiently schedule a task periodically?

I've got this code to schedule a task every so often:
final Handler handler = new Handler();
Runnable update = new Runnable() {
#Override
public void run() {
try{
runOnUiThread(new Runnable(){
public void run(){
lbl.setText(info);
cpb.setProgress(Float.valueOf(textInfo);
}
});
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
}
};
I want to constantly update the UI (every second, etc). The code works, however, the interface starts lagging. After the code iterates the task a few times the interface stops responding.
Is there any way I can schedule a task to repeat periodically without overloading the memory and without the interface lagging.
Assuming lbl is a TextView and cpb is a ProgressBar, your code will not considerably lag any device as it is. The problem lies somewhere else. Also, you appear to have missed a closing bracket on (Float.valueOf(textInfo);.
As an aside, you are unnecessarily using runOnUiThread inside the Runnable from what I can see. When you create a new Handler() it is implicitly linked to the calling thread's Looper, which I am assuming is the UI thread. In which case, the update Runnable will already be running on the UI thread. EDIT: This should not be the cause of the lag for the record, since iirc runOnUiThread checks if it is being executed on the UI thread then just runs it immediately, without doing another post.

Thread is not actually working

I'm a noobie in Java and Android I have a Thread question:
I have the following code that is triggered from android:onClick on the xml layout
The resulting behavior is that the UI waits 5 seconds and only after those 5 seconds, the ProgressDialog starts.
Shouldn't the Thread start independently and the dialog pop immediately?
Why is the Thread stopping the course of the procedure?
Thanks!
// (Button)
public void buttonReadGps(View v){
Thread readingGps = new Thread(){
public void run() {
// Read GPS code will go here
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
readingGps.run();
// Create a wait dialog
prgDialg = new ProgressDialog(context);
prgDialg.setTitle("Reading GPS...");
prgDialg.setMessage("Please wait.");
prgDialg.setCancelable(true);
prgDialg.setIndeterminate(true);
prgDialg.show();
}
Replace
readingGps.run();
with
readingGps.start();
The problem is the first version will just run your method synchronously and block the main thread. The second version actually starts a thread and continues, so the method will run asynchronously on a new thread.
This is such a common pattern in Android that the SDK gives a few classes to help: be sure to check out AsyncTask and possibly AsyncTaskLoader.

Handler/Runnable delays producing events that are out of sync sometimes

When trying to learn how to create a delay I researched and found the dominant answer to be to use Handler/Runnable/postDelayed.
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
delayedMethod();
}
};
handler.postDelayed(r, 1000);
That worked ok for a while, but I've added a few more things going on and now they are sometimes happening in the wrong order.
This set of events:
paintScreen1()
...
delayedPaintScreen2()
...
paintScreen3()
is screwing up (sometimes) and doing this:
paintScreen1()
...
paintScreen3()
...
delayedPaintScreen2() (runs last and gets messed up by the actions of paintScreen3)
There doesn't seem to be another good way to create delays - one that doesn't create threads.
Solutions I have tried in order to make sure the code events run in the proper order:
0 Putting the main process inside one big synchronized block.
1 Putting the synchronized keyword in the method name of every method involved in the main process.
2 Putting the synchronized keyword only on the method in the Runnable.
3 Taking away the Handler/Runnable/postdelayed and replacing with handler.sendEmptyMessageDelayed(0,1000)
4 Making one Handler instance variable, used by every Handler/Runnable block (as opposed to Handler handler1, handler2, handler3, etc.)
5
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
waitOver = true;
}
};
handler.postDelayed(r, 1000);
while (waitOver == false) {
}
delayedMethod();
waitOver = false;
My next attempt may be to try to used the Thread class somehow so I can call thread.join().
When that fails the next thing will be very long and complicated, I fear.
Any suggestions?
Any simple examples of a solution?
Thanks
Edit: I may be confused about whether Handler/Runnable results in literal threading or not.
Edit: It's a game. User makes a move, screen updated to show the move, calculation tells that they scored a point, recolor the boxes on the screen, add delay to allow user to see their point, then call method to removed colored squares, when that method completes and we return to the method that called it (containing the Handler/runnable), the code continues down to a point where it calls another method that results in a random square of the board being turned purple. So it should happen user-move, repaint to show point scored, delay so user can see point scored, repaint to erases squares, then random purple square happens. Sometimes what will happen (as far as I can tell) is the random purple square will execute before it should, choose one of the squares where the point was scored, interfere, and make it so the cleanup method gets confused and fails to cleanup.
mainmethod() {
...
if (pointscored) {
squaresglow();
...
//delay so user can see the glow before the cleanup happens
Handler-runnable
cleanup();
postdelayed
}
...
purpleSquare();
}
I hope this is not even more confusing. purpleSquare runs before cleanup and things get screwed up.
Edit:
Tried this:
6
CountDownLatch doneSignal = new CountDownLatch(1);
Handler handler=new Handler();
final LatchedRunnable lr = new LatchedRunnable(doneSignal);
handler.postDelayed(lr, COMPUTER_MOVE_DELAY);
try {
doneSignal.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
class LatchedRunnable implements Runnable {
private final CountDownLatch doneSignal;
LatchedRunnable(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
public void run() {
delayedProcess();
doneSignal.countDown();
}
}
7
ExecutorService executorService = Executors.newFixedThreadPool(5);
final CountDownLatch latch = new CountDownLatch(1);
executorService.execute(new Runnable() {
public void run() {
try {
Looper.prepare();
Handler handler=new Handler();
final Runnable r = new Runnable()
{
public void run()
{
delayedMethodCleanupCalc();
}
};
handler.postDelayed(r, 4000);
} finally {
latch.countDown();
}
}
});
try {
latch.await();
delayedMethodPaintScreen();
} catch (InterruptedException e) {
// todo >> handle exception
}
purpleSquare runs before cleanup and things get screwed up
mainmethod() {
...
if (pointscored) {
squaresglow();
...
//delay so user can see the glow before the cleanup happens
Handler-runnable
cleanup();
postdelayed
}
...
purpleSquare();
}
You have a design flaw here. Think of Handlers as a queue of messages that will execute code "later" whenever the processor decides to process messages and postDelayed as an inexact way to stuff that message at the bottom of the queue. If you call postDelayed and you still have lines of code left in the current method to execute, chances are very good that those lines will execute before postDelayed messages are even received.
What you are trying to do is to make sure purpleSquare() gets called after the pointscored routine has done it's job, which may require waiting for it to finish. PostDelaying to the message queue is not what you should be doing in this case. What you should be using is a semaphore and a pointScored thread.
Consider the following code design:
final Runnable pointScoredTask = new Runnable() {
public synchronized void run() {
try {
squaresglow();
//...
Thread.sleep(2500); //2.5 sec before cleanup occurs
cleanup();
} catch (InterruptedException e) {
}
notify(); //make sure we call notify even if interrupted
}
};
void mainmethod() {
//...
if (bPointWasScored) {
synchronized (pointScoredTask) {
try {
Thread psThread = new Thread(pointScoredTask,"pointscored");
psThread.start(); //thread will start to call run(), but we get control back to avoid race condition
pointScoredTask.wait(6000); //wait no more than 6 sec for the notify() call
} catch (InterruptedException e) {
}
}
//if a point was scored, nothing past this line will execute until scoreglow has been cleaned up
}
//...
purpleSquare();
//...
}
I know you'd rather avoid threads, but there are some things that just work much better when you use them. Try the above design and see if that works out the synchronization issues you were seeing.

To invoke a method of the main Thead From child thread

In my app i am using soap webservice call , based on the webservice call reply i have to display some messages .,
But after the reply i could not able to do this from the spawned child thread
So how to get back to the main thread and display this after the reply i got
Hope this is clear.. help me how to achieve my requirement
{
Thread t1 = new Thread() {
public void run() {
String threadName = Thread.currentThread().getName();
// There will be delay in this statement while fetching a data from webservice
String returnfromWebservice = webservice(xmlDetails, "generateid");
Log.v("returnfromWebservice",returnfromWebservice);
if( ! returnfromWebservice.equalsIgnoreCase("nil")){
gotid = returnfromWebservice;
gotReply=true;
// dothis();// I could able to do this because this method contains widgets
// I am gettin the error : Only the original thread that created a view hierarchy can touch its views.
//I understand this is because childthread has no controls on widget
/**Suggest me how to get back to main thread*/
}
}};
t1.start();
dothis();// so i am doin here after the completion of it
}
public void dothis{
if(gotReply){
idtext.setText(gotid);
genId.setEnabled(false);
Toast.makeText(WelcomeScorer.this, "Generated ", 500).show();
}
else{
Toast.makeText(WelcomeScorer.this, "Try Once More ", 500).show();
idtext.setText(gotid);
}
}
I am new to android, Is there any best approach in android api to handle this situation ??
You should use the following code to touch your ui elements from another thread
youractivityname.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
If your thread is in same activity you can use this. Otherwise you should use your activity class object to run the above method.From your code you should call dothis(); after thread has done its job. From your it will call the dothis method immediately after thread has started it wont care whether thread has done its job or not.
The various methods are documented in this article. Using runOnUiThread is probably the simplest.

Categories

Resources