Reputation: 43
I want to create a dialogBuilder with a text field and a button on it. The idea is to make the program wait for any further actions until the text in the field is entered and the OK button is clicked. Below is the code:
private static final Object wait = new int[0];
private static String result = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Handler h = new Handler();
final Context context = MainActivity.this;
h.post(new Runnable() {
public void run() {
final Builder dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.setTitle(R.string.app_name);
final LinearLayout panel = new LinearLayout(context);
panel.setOrientation(LinearLayout.VERTICAL);
final TextView label = new TextView(context);
label.setId(1);
label.setText(R.string.app_name);
panel.addView(label);
final EditText input = new EditText(context);
input.setId(2);
input.setSingleLine();
input.setInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_VARIATION_URI
| InputType.TYPE_TEXT_VARIATION_PHONETIC);
final ScrollView view = new ScrollView(context);
panel.addView(input);
view.addView(panel);
dialogBuilder
.setCancelable(true)
.setPositiveButton(R.string.app_name,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
result = input.getText().toString();
synchronized (wait) {
wait.notifyAll();
}
dialog.dismiss();
}
}).setView(view);
dialogBuilder.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
result = null;
synchronized (wait) {
wait.notifyAll();
}
}
});
dialogBuilder.create().show();
}
});
String localResult = null;
try {
synchronized (wait) {
Log.d("Waiting", "Waiting " + localResult);
wait.wait();
}
localResult = result;
result = null;
if (localResult == null) {
// user is requesting cancel
throw new RuntimeException("Cancelled by user");
}
Log.d("RESULT ", "RESULT " + localResult);
} catch (InterruptedException e) {
localResult = result;
result = null;
if (localResult == null) {
// user is requesting cancel
Log.d("CANCELED ", "CANCELED " + localResult);
throw new RuntimeException("Cancelled by user");
}
}
Log.d("RESULT AFTER THE DIALOG", "RESULT AFTER THE DIALOG " + result);
}
The program is going to Log.d("Waiting", "Waiting " + localResult); and after that just waiting. NO DIALOG BUILDER IS SHOWN on the activity window. I used the debug mode and saw that the program flow is not entering the run() method, but the value of the Handler.post() is true. And for this reason the dialog is not shown, and the program is waiting.
I have tried to remove the moment with waiting (remove the Handler.post()), just to see if the dialog will show, and it showed and all moved well, but the result was not I am needing - I want the program to wait the input from the dialog ... I am really out of ideas.
Would you please give me some suggestions as I am really out of ideas.
Thanks a lot!
Upvotes: 0
Views: 631
Reputation: 26547
Handlers
don't run in a separate thread. So when you call wait()
:
synchronized (wait) {
Log.d("Waiting", "Waiting " + localResult);
wait.wait();
}
It waits indefinitely since the handler runs on the same thread as the current thread. Your Runnable
can only be executed after the onCreate()
method finishes but this will never happen because you just called wait()
.
You should reconsider your idea and find a workaround (for example, show the dialog the usual way and disable the "OK" button as long as the user does not enter a valid text). But calling wait()
on the UI thread cannot go well.
Upvotes: 1
Reputation: 13541
You should be running the display of the Dialog in the UI Thread, not a seperate thread.
An example would be something like this:
runOnUiThread(new Runnable() {
@Override
public void run() {
// Display progress dialog when loading contacts
dialog = new ProgressDialog(this);
// continue with config of Dialog
}
});
// Execute the Asynchronus Task
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
// code to execute in background
return null;
}
@Override
protected void onPostExecute(Void result) {
// Dismiss the dialog after inBackground is done
if (dialog != null)
dialog.dismiss();
super.onPostExecute(result);
}
}.execute((Void[]) null);
Specifically what is happening here is the Dialog is being displayed on the UI thread and then the AsyncTask is executing in the background while the Dialog is running. Then at the end of the execution we dismiss the dialog.
Upvotes: 0