zanio
zanio

Reputation: 43

Android Handler - not working properly

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

Answers (2)

Dalmas
Dalmas

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

jtt
jtt

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:

In the onCreate()

                    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

Related Questions