AlertDialog не отображается из другого неактивного класса - PullRequest
0 голосов
/ 02 апреля 2019

Я пытаюсь показать диалоговое окно с предупреждением из другого класса.Я посмотрел много вопросов в StackOverflow, но ни один не работал.

У меня есть два класса MainActivity.java и CustomInputDialog.java.Я пытаюсь показать диалоговое окно оповещения от CustomInputDialog.java, которое указано в MainActivity.java.

В моем MainActivity.java у меня есть следующий код:

ArrayList<CustomInputDialog.Field> fields = new ArrayList<>(Arrays.asList(
                        new CustomInputDialog.Field(CustomInputDialog.Field.TYPE.TEXT, "Name", "", null),
                        new CustomInputDialog.Field(CustomInputDialog.Field.TYPE.DATE, "Start Date", "", null),
                        new CustomInputDialog.Field(CustomInputDialog.Field.TYPE.DATE, "End Date", "", null)
                ));

                ArrayList<String> result = CustomInputDialog.showDialog(MainActivity.this, "Title", fields);

В моем CustomInputDialog.javaУ меня есть следующий код:

final class CustomInputDialog {
    private static final String TAG = "CustomInputDialog";
    private static final String dateUISeparator = " : ";

    static ArrayList<String> showDialog(final Context context, String title, final ArrayList<Field> fields) {
        final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        final LinearLayout layout = new LinearLayout(context);
        layout.setOrientation(LinearLayout.VERTICAL);
        final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(10, 10, 10, 10);
        final ArrayList<View> uis = new ArrayList<>();
        for (final Field field : fields) {
            final View ui;
            switch (field.type) {
                 /**To long code it just creates specified views and saves it in `ui` variable*/
            }
            ui.setLayoutParams(layoutParams);
            Log.d(TAG, "showDialog: ui added");
            layout.addView(ui);
            uis.add(ui);
        }
        alertDialog.setTitle(title);
        alertDialog.setView(layout);

        final ArrayList<String> result = new ArrayList<>();
        Log.d(TAG, "showDialog: latch created");
        final CountDownLatch latch = new CountDownLatch(1);
        alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                /** Long code which updates `result` variable */
                dialog.dismiss();
                latch.countDown();
            }
        });
        alertDialog.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                latch.countDown();
                Log.d(TAG, "showDialog: latch count down 2");
            }
        });
        alertDialog.setCancelable(false);
        alertDialog.show();
        Log.d(TAG, "showDialog: showing");
        try {
            Log.d(TAG, "showDialog: latch await");
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (result.isEmpty()) {
                return null;
            } else {
                return result;
            }
        }
    }

    static final class Field {
        private final TYPE type;
        private final String helpText;
        private final String initialValue;
        private final int choice;

        enum TYPE {
            TEXT, DATE, DOUBLE, INTEGER, CHOICE
        }

        Field(TYPE type, String helpText, String initialValue, @Nullable Integer choice) {
            this.type = type;
            this.helpText = helpText;
            this.initialValue = initialValue;
            if (choice == null) {
                this.choice = 0;
            } else {
                this.choice = choice;
            }
        }
    }
}

Во время отладки выясняется, что не выдается никаких исключений, но переменная: alertDialog в методе showDialog не видна.

Выход системы:

D/CustomInputDialog: showDialog: ui created : editText
D/CustomInputDialog: showDialog: ui added
D/CustomInputDialog: showDialog: ui created : date
D/CustomInputDialog: showDialog: ui added
D/CustomInputDialog: showDialog: ui created : date
D/CustomInputDialog: showDialog: ui added
D/CustomInputDialog: showDialog: latch created
D/CustomInputDialog: showDialog: showing
D/CustomInputDialog: showDialog: latch await

1 Ответ

0 голосов
/ 02 апреля 2019

Проблема, похоже, исходит от CountDownLatch, который блокирует поток, вместо этого вы должны создать интерфейс в своем пользовательском диалоговом классе, где у вас есть onResult() (или как вы хотите это называть), который вы реализуете в другом месте.

Вам нужно будет передать слушателя вашему showDialog(), который реализует onResult(), и в вашей кнопке ОК onClick вы звоните listener.onResult()

Интерфейс (в CustomInputDialog.java):

interface CustomInputDialogListener{
    void onResult(ArrayList<String> result);
}

Новые параметры для передачи в showDialog:

static void showDialog(final Context context, String title, final ArrayList<Field> fields, final CustomInputDialogListener listener) {
...
}

Конец вашей кнопки ОК на клике ():

dialog.dismiss();
listener.onResult(result);
//latch.countDown(); //you don't need that anymore
Log.d(TAG, "showDialog: latch count down 1");

Вы можете удалить создание защелки и блок try / catch с помощью операторов wait и return в конце

//Log.d(TAG, "showDialog: latch created");
//final CountDownLatch latch = new CountDownLatch(1);

/*try {
    Log.d(TAG, "showDialog: latch await");
    latch.await();
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    if (result.isEmpty()) {
        return null;
    } else {
        return result;
    }
}*/

В вашем MainActivity.java у вас есть 2 варианта:

Реализация CustomInputDialogListener и передача этого в showDialog

Заголовок вашей MainActivity должен выглядеть следующим образом:

public class MainActivity extends AppCompatActivity implements CustomInputDialog.CustomInputDialogListener {
    ...
}

И вам придется реализовать onResult ():

@Override
public void onResult(ArrayList<String> result) {
    this.result = result;
    doThings();
}

И когда вы вызываете showDialog (), вы передаете это:

CustomInputDialog.showDialog(Test14dialog.this, "Title", fields, this);

Вы напрямую реализуете onResult:

CustomInputDialog.showDialog(Test14dialog.this, "Title", fields, new CustomInputDialog.CustomInputDialogListener() {
        @Override
        public void onResult(ArrayList<String> result) {
            this.result = result;
            doThings();
        }
    });

Вы не должны блокировать потоки при отображении диалогового окна.

...