Dialogs / AlertDialogs: How to "block execution" while dialog is up (.NET-style)
In Android, the structure is different from .NET:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Hello!")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Handle Ok
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Handle Cancel
}
})
.create();
Will get you a dialog with two buttons and you handle the button clicks with callbacks. You might be able to write some code to make the syntax more closely resemble .NET, but the dialog lifecycle is pretty intertwined with Activity
, so in the end, it might be more trouble than it's worth. Additional dialog references are here.
In Android Dialogs are asynchronous so you're going to have to structure your code a little differently.
So in C# your logic ran something like this in pseudocode:
void doSomeStuff() {
int result = showDialog("Pick Yes or No");
if (result == YES) {
//do stuff for yes
}
else if (result == NO) {
//do stuff for no
}
//finish off here
}
For Android it's going to have to be less neat. Think of it like so. You'll have an OnClickListener
like this:
public void onClick(DialogInterface dialog, int whichButton) {
if (whichButton == BUTTON_POSITIVE) {
doOptionYes();
}
else if (whichButton == BUTTON_NEGATIVE) {
doOptionNo();
}
}
Which is then supported by the following methods:
void doOptionYes() {
//do stuff for yes
endThings();
}
void doOptionNo() {
//do stuff for no
endThings();
}
void endThings() {
//clean up here
}
So what was one method is now four. It may not seem as neat but that's how it works I'm afraid.
Ted, you don't want to do this, really :) The biggest reason is that if you block the UI thread while you are displaying a Dialog, you will block the thread that's in charge of drawing and handling the events of your Dialog. Which means your dialog will be unresponsive. You will also cause ANRs if the user takes more than a few seconds to click the dialog.
Erich's answer is exactly what you need. I know it's not what you want, but that doesn't matter. We've designed Android to prevent developers from writing synchronous dialogs so you don't really have much of a choice.
A simplified version of Daniel's answer above. This function gets a yes or no from user in an alert dialog but could easily be modified to get other input.
private boolean mResult;
public boolean getYesNoWithExecutionStop(String title, String message, Context context) {
// make a handler that throws a runtime exception when a message is received
final Handler handler = new Handler() {
@Override
public void handleMessage(Message mesg) {
throw new RuntimeException();
}
};
// make a text input dialog and show it
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(title);
alert.setMessage(message);
alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mResult = true;
handler.sendMessage(handler.obtainMessage());
}
});
alert.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
mResult = false;
handler.sendMessage(handler.obtainMessage());
}
});
alert.show();
// loop till a runtime exception is triggered.
try { Looper.loop(); }
catch(RuntimeException e2) {}
return mResult;
}