Context
I need to manage the concurrency of an app. I declared a Object sync to use monitors on that object.
The main goal is that the first button, A, will execute some code, but, when reaching some points, it needs button B to be clicked to be able to continue. Something like this:
Issues
The issue is that the B button can't be clicked, I guess it's because the UI thread is stuck waiting for the code of button A to be fully executed before raising other button events.
If I execute the code in button A in a new Thread, when I try to update the View (called UI in the drawing), I get CalledFromWrongThreadException.
Edit
I solved it adding a Handler for the UI update and the already added Thread for the code in A.
Factor the code that is taking the time into a Runnable that you execute in a separate thread, but once you've started that thread, do the UI update in the original thread.
Related
Well I just want to press a button and a countdown appears in it however when I press the button the program stops and finally shows the number 1 but doesn't show 3 or 2.
btnTurno.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v) {
btnTurno.setText("3");
SystemClock.sleep(1000);
btnTurno.setText("2");
SystemClock.sleep(1000);
btnTurno.setText("1");
}
});
What I'm doing wrong?
First of all, Sleep should be called as Thread.sleep(x);
But on the other hand , sleep is NOT recommended since it will block the user interaction with the application.
If you want to make a countdown ( as it looks like what you are doing ), you should look at this
http://developer.android.com/reference/android/os/CountDownTimer.html
onClick is being executed in single handler message on GUI thread, so each time you change text, it overwrites previous value, so system is not able to redraw view.
Also you should not call sleep() on main gui thread, that will cause ANR - application is notresponding
Setting the text and drawing the text are separate operations that both happen on the same thread. You're setting the text three times before the framework gets the chance to draw anything, so all you see is the last change.
For this to work, you'd need to do your text updates and sleeps on a separate thread. However, you can't make UI calls directly on a different thread, so you need to post your messages.
One approach would be to create an AsyncTask, and use your code above but call publishProgress() where you're currently calling setText(). The publishProgress() call in the async thread results in onProgressUpdate() running in the UI thread; from there, you can call setText() to update the UI.
Edit: the CountDownTimer approach mentioned in a different answer is better.
I know it sounds crazy that someone is using runOnUiThread inside AsyncTask. Somehow, it is working for me but I wanna know if it is an acceptable and robust approach or not. Here is the scenario:
I have an app in which after successful login, user is rendered to next screen. In this new screen, 3 different methods are loading different types of data from a web server. These methods are:
getMembersForList() : It loads the list of community members and shows it in a listview.
getProfileData() : It loads the profile of logged in user and shows his name , image etc on the screen.
getNotificationCounts : It loads the count of new notifications for the user.
I applied 3 different approaches for it :
(1) Calling all 3 methods simply in onCreate i.e. no exclusive thread is being used for any of the methods . In this case , the transition from login screen to this screen becomes very slow and black screen shows up for some time before this activity shows up.
(2) Calling getMembersForList() on UI thread and the other 2 methods on exclusive threads. In this case transition becomes fast and list shows up quickly but Notification counts and username etc. don't show up because WrongThreadException occurs saying that this thread can't touch other thread's views (TextViews for username, notification count etc. which are declared globally) . The same thing happens when I start these threads from an AsyncTask as well.
(3) Calling getMembersForList() on UI thread and then starting an AsyncTask in which the other 2 methods are being called in "runOnUiThread" inside doInBackground() method. This solves both the above issues. Now the screen transition is faster and the WrongThread exception is also not occuring.
So far the approach-(3) is working good for me but I am not sure if this is the right way to do it because runOnUiThread and AsyncTask are 2 completely opposite things. Can anyone please clear my doubts about this scenario. Thanx in advance.
Yes, use-cases like this are a big reason why the runOnUiThread() method exists in the first place. The idea is you allow your background thread(s)/AsyncTask instance(s) to run your lengthy operations in the background, and then provide a simple hook that they can use to update the interface when they have the result (or at arbitrary intervals, as different pieces of the result become available).
As long as that's what you're doing, then your usage is fine. What you want to avoid doing is performing a lengthy operation on the main thread, either directly or indirectly by passing in some lengthy operation from a background thread.
Of course you don't have to do it that way if you don't want to. You could use postExecute() instead. Or you could store the result somewhere and then use any sort of message-passing API to notify the main thread that the result is ready, and so on.
I would advice to run all the 3 calls in the asyncTask, and update the UI in the postExecute() of the AsyncTask after the background taks is complete, postExecute runs on UIthread so you need not call anything explicit to run them on UIthread.
I'm trying to implements a game AI, and I got the following problem :
I'm calling a method from another class my UI Activity class, this method call itself some methods of the UI Activity class (to simulate click on screen among other things), and the things is, at the end of this method, I need to "pause" the game a few seconds to let the user see what did the AI.
So I tried running the method in another thread, but I got the error message providing from editing a widget from another thread. I tried to sleep the UI thread, but by doing that, the user can't use the scrollview anymore, and the changes aren't display before the sleep but after.
So I'd like to know how can I do this ?
(I've read some topics about AsyncTask, Handler, but can't make it work the way I need)
Thank's
You need runOnUiThread.
http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
http://steve.odyfamily.com/?p=12
This may have been hidden somewhere in the docs, but I don't remember seeing it:
Assuming everything is running on the same thread, would an activity callback, or any kind of callback for that matter, interrupt a runnable , or even some other callback, executing on the thread, or are they posted sequentially by time of occurance as messages similar to runnables?
It certainly doesn't interrupt execution, at least in the UI thread. For instance, say that you have a Button, and you place a Thread.sleep(10000) in its onClick callback. Well, as soon as you press the button the entire UI will freeze. This wouldn't happen if the onClick callback interrupted the UI thread's execution.
If you wanted to know all the answer of the question you need to use
http://developer.android.com/guide/developing/debugging/debugging-tracing.html
Depends on the Runnable.
All activity callbacks happen in the UI Thread. For example thread for onCreate is same as the thread which calls onTabSelected.
If you are started an AsyncTask, it runs in its own thread.
Try using following Log statement to check your scenario
Log.i("","Thread Id : "+Thread.currentThread().getId());
Is it possible to execute an AsyncTask from Runnable? in my experience it can be done, but not safely. When my app first runs my AsyncTask runs fine from the Runnable. But when the app is moved to the background, then brought back forward I get "Can't create handler inside thread that has not called Looper.prepare()".
Here's what I'm trying to do:
I'm using MapView and invoking runOnFirstFix(Runnable) within onCreate. My Runnable calls an AsyncTask to perform a web service call which returns some data based on the location.
I move the app to the background (by tapping the home button), after some time I bring my app forward again and I'm getting the exception at the point where I'm invoking execute() on my AsyncTask.
First of all, why is runOnFirstFix being executed again? Secondly, why is it causing the exception the second time around?
I'm guessing that there is some part of the lifecycle that I don't understand.
Thanks.
It wasn't initially obvious to me that the AsyncTask needed to be called from the UI thread. So when runOnFirstFix ran the second time it was from withing a Runnable which wasn't on the UI thread. To solve the problem I simple created another Runnable inside the first to run the AsynchTask.
And the reason my runOnFirstFix seemed to be called twice was simply because I was creating a new instance of it.