I have a function that creates a socket connection and then waits for a response. During this time I do not want the user to be able to click any buttons, else they can crash the application.
as such at the start of the function I do the following:
public void Checkout()
{
AlertDialog.Builder builder2 = new AlertDialog.Builder(NuPos_testActivity.this);
builder2.setMessage("Processing");
AlertDialog alert2 = builder2.create();
alert2.show();
This greys out the screen and displays processing till the response comes back from the server. My problem is while this is the first thing at the top of the function it only runs after everything else. I don't understand why?
To be more clear about my problem: I run an alert box before code, but it only shows after the code has finished running. how do I fix this?
Showing an AlertDialog doesn't halt the code. It just prevents user interaction. If you want to delay further code execution until you are ready, look at something like ASyncTask which has an onPostExecute() method to notify you when the task is complete.
It sounds like your code sample above, and the code for your Socket, are running in the same Thread (which is the UIThread). If this is the case, Android will usually perform the 'processing' code first, and delay the painting until afterwards (as the painting has a lower priority).
You need to move the Socket code into a separate Thread, so that it can run independently from the UIThread, which should allow Android the time to display the AlertDialog earlier.
Related
Following situation:
I code a Domino game for Android. At the beginning of the game, if not a bot is the starting player, a user should pick two Dominos that get onto the board.
Overview of my non-working approach:
Definition of an empty ArrayList, call of a function that attaches Click Listeners on every Domino belong to the user followed by a while loop that does nothing, should just be the mechanism to wait until the user has picked two dominos. These dominos should be stored in the ArrayList(adding of the dominos to the ArrayList in FirstDominosPickerListener)
The code
In the activity:
ArrayList<Domino> starterDominos = new ArrayList<Domino>();
startingPlayer.chooseStartDominos(starterDominos);
the function:
public void chooseStartDominos(ArrayList<Domino> starterDominos){
///Every Domino gets a ClickListener
for (Domino domino : playerSet){
domino.setOnClickListener(new FirstDominosPickerListener( starterDominos));
}
//The idea is to wait until the user has picked two Dominos. With that loop, no UI at all shows up
while (starterDominos.size()<2){
Log.v(LOG_TAG," WAIT!!!!");
}
}
The problem is the while Loop. With the loop, no UI shows up, i get an empty white screen, altough the code runs. In logcat, i get infinite "Wait" messages. No idea why.
A second approach I've tried was to call a Timer task in the activity after that checks if two dominos were picked (through the size of the list) starterDominos = startingPlayer.chooseStartDominos(starterDominos);
I realized that couldn't work because that runs in another thread and because of that, it wasn't possible to access any part of the UI. But the mechanism to pick the dominos worked. UI showed up and run() ended after two dominos were picked through cancel().
So why does the while loop leads to that behavior? Is the whole approach wrong and if so what can I do that the app waits until the dominos were picked and then proceed
Your while loop is blocking the main UI thread so nothing can be drawn or updated on the screen. You need to set up a listener for when a user selects a domino, then proceed after a user has selected two dominos.
You can use a class variable in the activity class 'userDominoSelectCount' which can be a short integer field initialized to 0.
You can add the onClickListener for domino in the activity onCreate method itself:
domino.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
++userDominoSelectCount;
if(userDominoSelectCount == 2){
//initiate AI logic
userDominoSelectCount = 0;
}
}
});
The way you are doing will block the main thread as mentioned in other answer to the question. OnClicklisteners are meant to be run in event loop and ideally should not block UI.
I have a question about the Android Studio:
I have an Image view. Let's call it ImageView. I call the method setOnCLickListener on this ImageView with a listener new View.OnclickListener().
In the method onClick() of this listener, I change an attribute (the color, the image itself...) of this imageView. For example, I change the image with imageView.setImageResource(R.drawable.new_image). I then wait for 10 sec with Thread.sleep(10000). I then set back the previous image with imageView.setImageResource(R.drawable.previous_image).
Here is my question:
I expect the ImageView to change its image for 10 sec and then have the previous image back. However, I see no change on this ImageView. I only see the first image...Could someone explain me why?
I hope I was clear enough...Thank you in advance for your help :) !!
R.id.drawable.previous_image ?. It should be R.drawable.previous_image
First of all, you should read the Processes and Threads guide to understand how threading works on Android.
If you're done with with that, you'll understand that what you do is really bad because you freeze the main (UI) thread which means the application will not respond to any events until the 10 seconds pass. This also results in an ANR (Application Not Responding) dialog which is pretty bad UX.
You basically need to delegate the waiting period to another thread (or a queue at least), then when the time comes, go back to the UI thread and set whatever view attribute you want. There are many ways to achieve this, you should read Communicating with the UI Thread for more details. Here's just a quick sample:
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
// write here what you want to happen in 10 seconds on the UI thread
}
}, 10000); // 10s = 10,000ms
Here are some notes though:
Save the Runnable you create here to a variable because if the user navigates away from this screen within the 10 seconds, it will still run the code inside, which might result in various exceptions. In this case you need to remove that Runnable from the handler by calling handler.removeCallbacks(runnable); when the user leaves the screen.
Don't create a new Handler instance every time the click event happens. Create it in the Activity's onCreate(...) method and use that instance in the rest of the screen.
You could create the Handler without the Looper parameter, which would create the handler for the current thread's Looper and that would be fine now since it's being created on the UI thread. However, I decided it's better to show you the safer way since you might end up doing something similar on a background thread that could result in unexpected behavior if you don't understand the threading yet.
So this is a tuff one. I have a activity that calls a class that call a http downloader which is the async task. What I want to do is have a please wait loading screen notification for the user while the activity is getting all the data from the web. I don't have a clue on how to get the loading screen to be called. Usually you would have it in the async task but my async task does not have a view. How to best go about doing this?
Thank you for any help.
My http client does have a doInBackground() so should I put the on preExecute and postExecute there? But then how would my main method which is twice removed know when its down and when its not.
What is happening is that when a button is clicked it starts the activity and starts to process all the methods, but it linger on the first activity until everything is done loading. I don't want that I want the progress dialog. It just won't show. Any thoughts on this?
NEW UPDATES
Ok so now I got this set up a bit better so now at least the progress dialog now shows up. the problem is the Async task does not stop running.
You should use an AsyncTask. It doesn't have to have a view, it's just a background process just like a thread.
Refer to this on how to use an AsyncTask properly with a ProgressDialog.
Do your methods in the doInBackground() method of the AsyncTask.
I've got a button that kicks off a background thread to do some work and I am trying to use a ProgressDialog to prevent the user from double clicking that button (or any other ui elements) while that work is being done. The first thing I do in my buttons onClick code is to display the progress dialog, which takes over the screen. The problem I am seeing is that if I rapidly tap this button, sometimes two or more presses will register before the ProgressDialog is shown. This leads me to assume that ProgressDialog.show() is returning before the ProgressDialog is actually visible.
Can anybody confirm this? Also, is there a way to change this behavior, or at least get a notification of when the dialog is actually visible? I saw Dialog.onStart() but given the javadoc, this appears to be called before the Dialog is actually visible...
UPDATE:
While it appears that there is no good way of solving this problem in general, the following works for my situation where my work is done by an external thread and the amount of work to do takes longer than the time it takes for all the button clicks to be processed:
void myOnClickHandler() {
if(myButton.isEnabled()) {
myButton.setEnabled(False);
// do work here
// setEnabled(true) is invoked at the end of my spawned thread's run().
}
}
No.
The problem is you clicked many times before the click event is delivered. (i.e. it is queued before you run ProgressDialog.show().)
From what I've noticed in Android you can double click on a button rapidly and have the onClick listener fire twice (or even more) regardless of the code in the listener (even if you disable the button immediately).
I reported a bug a while ago here: http://code.google.com/p/android/issues/detail?id=20073 but of course these things tend to go "unnoticed" by Google. Feel free to star it in hopes of getting Google's attention
I am creating a matching game for Android, and when the user gets a match, a dialog box should pop up saying "Match!" I cannot figure out how to do this though. If I use Thread.currentthread().sleep, the dialog never appears.
android.app.AlertDialog a = new android.app.AlertDialog.Builder(match.this).setTitle("Match!").show();
Thread.currentthread().sleep(1000);
a.dismiss();
Nothing happens - the program just hangs for a second. I would like it to pop up for just 1 second, or if there is another sort of popup type thing, that would be good too.
You're trying to show a text message in a popup for a short period of time on the screen?
For these kind of alerts toasts are great:
Toast.makeText(this, "Match!", Toast.LENGTH_LONG).show();
Is that what you are looking for?
Here is the Java Doc.
The dialog is shown in the current thread but you are putting the thread to sleep so it never shows up. Other than event throttling, there are few cases where you want to call sleep with a substantial delay from the UI thread.
In this case using a Toast is easiest as the previous poster suggested. A couple of other ways to handle work you want done in the future
Java Timers. The action will happen
on a different thread so you have to
be carefull what gui calls you make
Views have a postDelayed(Runnable action, long delayMillis) method will cause the Runnable to be executed on the UI thread after roughly delayMillis.