Android DialogFragment vs Dialog


244

Google рекомендує використовувати DialogFragmentзамість простого Dialogвикористання Fragments API, але абсурдно використовувати ізольоване DialogFragmentдля простого вікна підтвердження "Так-Ні". Яка найкраща практика в цьому випадку?


5
Коротше кажучи, серед іншого, простий Dialogабо AlertDialog.Builder::create()::show()створить діалогове вікно, яке зникає при повороті екрана.
користувач1032613

Відповіді:


83

Так, використовуйте DialogFragmentі в onCreateDialogбудь-якому випадку ви можете просто використовувати конструктор AlertDialog, щоб створити простий за AlertDialogдопомогою кнопок підтвердження Так / Ні. Не дуже багато коду взагалі.

Що стосується обробки подій у вашому фрагменті, то існують різні способи його виконання, але я просто визначаю повідомлення Handlerу своєму Fragment, передаю його DialogFragmentчерез його конструктор і потім передаю повідомлення назад до обробника мого фрагмента як відповідного для різних подій клацання. Знову різні способи зробити це, але наступне для мене працює.

У діалоговому вікні утримуйте повідомлення та інстанціюйте його у конструкторі:

private Message okMessage;
...
okMessage = handler.obtainMessage(MY_MSG_WHAT, MY_MSG_OK);

Реалізуйте onClickListenerдіалогове вікно у своєму діалоговому вікні, а потім зателефонуйте оброблювачу відповідно

public void onClick(.....
    if (which == DialogInterface.BUTTON_POSITIVE) {
        final Message toSend = Message.obtain(okMessage);
        toSend.sendToTarget();
    }
 }

Редагувати

І як Messageце можна розділити, ви можете зберегти його onSaveInstanceStateта відновити

outState.putParcelable("okMessage", okMessage);

Тоді в onCreate

if (savedInstanceState != null) {
    okMessage = savedInstanceState.getParcelable("okMessage");
}

4
Проблема не є okMessage - проблема okMessage, targetяка буде нульовою, якщо ви завантажуєте її з пакета. Якщо ціль Повідомлення є нульовою, і ви використовуєте sendToTarget, ви отримаєте NullPointerException - не тому, що Повідомлення є нульовим, а тому, що його метою є.
hrnt

2
Які переваги використання DialogFragment замість Dialog?
Рафаель Петегроссо

80
Перевага використання DialogFragment полягає в тому, що весь життєвий цикл діалогу буде оброблятися для вас. Ви ніколи не отримаєте помилку, "діалогове вікно просочилося ..." знову. Перейдіть до DialogFragment і забудьте діалоги.
Snicolas

6
Я думаю, що setArguments () та getArguments () слід використовувати замість передачі okMessage через конструктор.
pjv

1
Ну я користувач Builder досить легко, і я керую управлінням діяльністю за допомогою цього андроїда: configChanges = "locale | клавіатураHidden | орієнтація | screenSize", і я не бачу проблем у додатках ...
Renetik

67

Ви можете створити загальні підкласи DialogFragment, такі як YesNoDialog та OkDialog, і передати заголовок та повідомлення, якщо у вашому додатку багато використовуються діалоги.

public class YesNoDialog extends DialogFragment
{
    public static final String ARG_TITLE = "YesNoDialog.Title";
    public static final String ARG_MESSAGE = "YesNoDialog.Message";

    public YesNoDialog()
    {

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Bundle args = getArguments();
        String title = args.getString(ARG_TITLE);
        String message = args.getString(ARG_MESSAGE);

        return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, null);
                }
            })
            .create();
    }
}

Потім зателефонуйте за допомогою наступного:

    DialogFragment dialog = new YesNoDialog();
    Bundle args = new Bundle();
    args.putString(YesNoDialog.ARG_TITLE, title);
    args.putString(YesNoDialog.ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(this, YES_NO_CALL);
    dialog.show(getFragmentManager(), "tag");

І обробляти результат в onActivityResult.


Так, DialogFragment обробляє всі події життєвого циклу для вас.
ашішдух

1
Я думаю, що це не так, тому що після обертання старий діалог все ще існує, і він зберігає відношення до старого неіснуючого фрагмента (dialog.setTargetFragment (це, YES_NO_CALL);), тому після обертання getTargetFragment (). OnActivityResult не працює
Malachiasz

7
що таке YES_NO_CALL, getFragmentManager()і onActivityResult?
msysmilu

2
YES_NO_CALL- це спеціальний int, який є кодом запиту. getFragmentManager()отримує менеджер фрагментів для активності та onActivityResult()метод зворотного виклику фрагмента життєвого циклу.
ашішдух

3
Замініть getFragmentManager () на getSupportFragmentManager ();
Авінаш Верма

33

Використовуйте DialogFragment над AlertDialog:


  • З моменту впровадження API рівня 13 :

    ShowDialog метод від діяльності є застарілим . Викликати діалог в інше місце в коді не рекомендується, оскільки вам доведеться самостійно керувати діалогом (наприклад, зміна орієнтації).

  • Різниця DialogFragment - AlertDialog

    Чи так вони різні? З посилання на Android щодо DialogFragment :

    ДіалогФрагмент - це фрагмент, який відображає діалогове вікно, що плаває вгорі вікна своєї діяльності. Цей фрагмент містить об'єкт "Діалог", який він відображає відповідно до стану фрагмента. Контроль діалогу (прийняття рішення , коли потрібно показати, приховати, відхилити його) має бути зроблено через API тут , а не прямим виклики на діалозі.

  • Інші примітки

    • Фрагменти - це природна еволюція в рамках Android, завдяки різноманітності пристроїв різного розміру екрана.
    • DialogFragments та Fragments доступні в бібліотеці підтримки, що робить клас доступним для використання в усіх поточних використовуваних версіях Android.

28

Я б рекомендував використовувати DialogFragment.

Звичайно, створення діалогового вікна "Так / Ні" досить складне, враховуючи, що це має бути досить простою задачею, але створення подібного діалогового вікна також Dialogнапрочуд складне.

(Життєвий цикл діяльності ускладнює його. Ви повинні дозволити Activityкерувати життєвим циклом діалогового вікна - і немає можливості передавати спеціальні параметри, наприклад, користувацьке повідомлення, Activity.showDialogякщо використовуєте рівні API до 8)

Приємно те, що зазвичай ви можете побудувати власну абстракцію поверх DialogFragmentдуже легко.


Як ви будете працювати з зворотними дзвінками діалогового оповіщення (так, ні)?
Олексій Захаров

Найпростішим способом було б реалізувати метод в хостинговій діяльності, який приймає Stringпараметр. Наприклад, коли користувач натискає "Так", діалогове вікно викликає метод діяльності з параметром "погодитися". Ці параметри задаються під час відображення діалогового вікна, наприклад AskDialog.ask ("Чи згодні ви з цими умовами?", "Згодні", "не згодні");
hrnt

5
Але мені потрібен зворотний виклик всередині фрагмента, а не активність. Я можу використовувати setTargetFragment і передавати його в інтерфейс. Але це пекло.
Олексій Захаров

Ви можете також принести цільової фрагмент, встановивши мітку до мети і з допомогою FragmentManager«S findFragmentByTag. Але так, це вимагає неабиякого коду.
hrnt

@AlexeyZakharov Я знаю, що це на 5 років пізніше, але ви можете пройти Fragment this і мати Activity extendsсвоє Interface. Але обережно вкладаючи нитки, ви можете відмовлятись від інтерфейсних дзвінків, коли ви не обов'язково хочете їх, якщо ваша паралельність не перевірена. Не впевнений, що це стосується спагетті пам’яті та кругової залежності, чи хотів би хтось ще подзвонити? Інший варіант - Message/ Handlerале у вас все ще можуть виникнути проблеми з одночасністю.
хитрологія

8

Загальний AlertDialogFragment з малюнком Builder

У моєму проекті, я вже використав AlertDialog.Builderуже багато , перш ніж я дізнався, що це проблематично. Однак я не хотів змінювати стільки коду в будь-якому місці свого додатка. Крім того, я фактично прихильник проходження OnClickListenersанонімних класів там, де вони потрібні (тобто під час використання setPositiveButton(),setNegativeButton() і т.д.) , замість того , щоб реалізувати тисячі методів зворотного виклику для обміну даних між діалоговим фрагментом і фрагментом власника, який може, в на мою думку, ведуть до дуже заплутаного та складного коду. Тим більше, якщо у вас є декілька різних діалогів в одному фрагменті, а потім потрібно розрізняти в реалізаціях зворотного виклику, між якими діалоговими вікнами в даний момент показано.

Тому я поєднав різні підходи, щоб створити загальний AlertDialogFragmentклас помічників, який можна використовувати саме так AlertDialog :


РІШЕННЯ

( ВВАЖАЙТЕ, що я використовую лямбда-вирази Java 8 у своєму коді, тому вам, можливо, доведеться змінити частини коду, якщо ви ще не використовуєте лямбда-вирази .)

/**
 * Helper class for dialog fragments to show a {@link AlertDialog}. It can be used almost exactly
 * like a {@link AlertDialog.Builder}
 * <p />
 * Creation Date: 22.03.16
 *
 * @author felix, http://flx-apps.com/
 */
public class AlertDialogFragment extends DialogFragment {
    protected FragmentActivity activity;
    protected Bundle args;
    protected String tag = AlertDialogFragment.class.getSimpleName();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activity = getActivity();
        args = getArguments();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = setDialogDefaults(new AlertDialog.Builder(getActivity())).create();

        if (args.containsKey("gravity")) {
            dialog.getWindow().getAttributes().gravity = args.getInt("gravity");
        }

        dialog.setOnShowListener(d -> {
            if (dialog != null && dialog.findViewById((android.R.id.message)) != null) {
                ((TextView) dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
            }
        });
        return dialog;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);

        if (args.containsKey("onDismissListener")) {
            Parcelable onDismissListener = args.getParcelable("onDismissListener");
            if (onDismissListener != null && onDismissListener instanceof ParcelableOnDismissListener) {
                ((ParcelableOnDismissListener) onDismissListener).onDismiss(this);
            }
        }
    }

    /**
     * Sets default dialog properties by arguments which were set using {@link #builder(FragmentActivity)}
     */
    protected AlertDialog.Builder setDialogDefaults(AlertDialog.Builder builder) {
        args = getArguments();
        activity = getActivity();

        if (args.containsKey("title")) {
            builder.setTitle(args.getCharSequence("title"));
        }

        if (args.containsKey("message")) {
            CharSequence message = args.getCharSequence("message");
            builder.setMessage(message);
        }

        if (args.containsKey("viewId")) {
            builder.setView(getActivity().getLayoutInflater().inflate(args.getInt("viewId"), null));
        }

        if (args.containsKey("positiveButtonText")) {
            builder.setPositiveButton(args.getCharSequence("positiveButtonText"), (dialog, which) -> {
                onButtonClicked("positiveButtonListener", which);
            });
        }

        if (args.containsKey("negativeButtonText")) {
            builder.setNegativeButton(args.getCharSequence("negativeButtonText"), (dialog, which) -> {
                onButtonClicked("negativeButtonListener", which);
            });
        }

        if (args.containsKey("neutralButtonText")) {
            builder.setNeutralButton(args.getCharSequence("neutralButtonText"), (dialog, which) -> {
                onButtonClicked("neutralButtonListener", which);
            });
        }

        if (args.containsKey("items")) {
            builder.setItems(args.getStringArray("items"), (dialog, which) -> {
                onButtonClicked("itemClickListener", which);
            });
        }

        // @formatter:off
        // FIXME this a pretty hacky workaround: we don't want to show the dialog if onClickListener of one of the dialog's button click listener were lost
        //       the problem is, that there is no (known) solution for parceling a OnClickListener in the long term (only for state changes like orientation change,
        //       but not if the Activity was completely lost)
        if (
                (args.getParcelable("positiveButtonListener") != null && !(args.getParcelable("positiveButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("negativeButtonListener") != null && !(args.getParcelable("negativeButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("neutralButtonListener") != null && !(args.getParcelable("neutralButtonListener") instanceof ParcelableOnClickListener)) ||
                (args.getParcelable("itemClickListener") != null && !(args.getParcelable("itemClickListener") instanceof ParcelableOnClickListener))
        ) {
            new DebugMessage("Forgot onClickListener. Needs to be dismissed.")
                    .logLevel(DebugMessage.LogLevel.VERBOSE)
                    .show();
            try {
                dismissAllowingStateLoss();
            } catch (NullPointerException | IllegalStateException ignored) {}
        }
        // @formatter:on

        return builder;
    }

    public interface OnDismissListener {
        void onDismiss(AlertDialogFragment dialogFragment);
    }

    public interface OnClickListener {
        void onClick(AlertDialogFragment dialogFragment, int which);
    }

    protected void onButtonClicked(String buttonKey, int which) {
        ParcelableOnClickListener parcelableOnClickListener = getArguments().getParcelable(buttonKey);
        if (parcelableOnClickListener != null) {
            parcelableOnClickListener.onClick(this, which);
        }
    }

    // region Convenience Builder Pattern class almost similar to AlertDialog.Builder
    // =============================================================================================

    public AlertDialogFragment builder(FragmentActivity activity) {
        this.activity = activity;
        this.args = new Bundle();
        return this;
    }

    public AlertDialogFragment addArguments(Bundle bundle) {
        args.putAll(bundle);
        return this;
    }

    public AlertDialogFragment setTitle(int titleStringId) {
        return setTitle(activity.getString(titleStringId));
    }

    public AlertDialogFragment setTitle(CharSequence title) {
        args.putCharSequence("title", title);
        return this;
    }

    public AlertDialogFragment setMessage(int messageStringId) {
        return setMessage(activity.getString(messageStringId));
    }

    public AlertDialogFragment setMessage(CharSequence message) {
        args.putCharSequence("message", message);
        return this;
    }

    public AlertDialogFragment setPositiveButton(int textStringId, OnClickListener onClickListener) {
        return setPositiveButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setPositiveButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("positiveButtonText", text);
        args.putParcelable("positiveButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNegativeButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNegativeButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNegativeButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("negativeButtonText", text);
        args.putParcelable("negativeButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setNeutralButton(int textStringId, AlertDialogFragment.OnClickListener onClickListener) {
        return setNeutralButton(activity.getString(textStringId), onClickListener);
    }

    public AlertDialogFragment setNeutralButton(CharSequence text, AlertDialogFragment.OnClickListener onClickListener) {
        args.putCharSequence("neutralButtonText", text);
        args.putParcelable("neutralButtonListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setOnDismissListener(OnDismissListener onDismissListener) {
        if (onDismissListener == null) {
            return this;
        }

        Parcelable p = new ParcelableOnDismissListener() {
            @Override
            public void onDismiss(AlertDialogFragment dialogFragment) {
                onDismissListener.onDismiss(dialogFragment);
            }
        };
        args.putParcelable("onDismissListener", p);
        return this;
    }

    public AlertDialogFragment setItems(String[] items, AlertDialogFragment.OnClickListener onClickListener) {
        args.putStringArray("items", items);
        args.putParcelable("itemClickListener", createParcelableOnClickListener(onClickListener));
        return this;
    }

    public AlertDialogFragment setView(int viewId) {
        args.putInt("viewId", viewId);
        return this;
    }

    public AlertDialogFragment setGravity(int gravity) {
        args.putInt("gravity", gravity);
        return this;
    }

    public AlertDialogFragment setTag(String tag) {
        this.tag = tag;
        return this;
    }

    public AlertDialogFragment create() {
        setArguments(args);
        return AlertDialogFragment.this;
    }

    public AlertDialogFragment show() {
        create();
        try {
            super.show(activity.getSupportFragmentManager(), tag);
        }
        catch (IllegalStateException e1) {

            /**
             * this whole part is used in order to attempt to show the dialog if an
             * {@link IllegalStateException} was thrown (it's kinda comparable to
             * {@link FragmentTransaction#commitAllowingStateLoss()} 
             * So you can remove all those dirty hacks if you are sure that you are always
             * properly showing dialogs in the right moments
             */

            new DebugMessage("got IllegalStateException attempting to show dialog. trying to hack around.")
                    .logLevel(DebugMessage.LogLevel.WARN)
                    .exception(e1)
                    .show();

            try {
                Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
                mShownByMe.setAccessible(true);
                mShownByMe.set(this, true);
                Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
                mDismissed.setAccessible(true);
                mDismissed.set(this, false);
            }
            catch (Exception e2) {
                new DebugMessage("error while showing dialog")
                        .exception(e2)
                        .logLevel(DebugMessage.LogLevel.ERROR)
                        .show();
            }
            FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
            transaction.add(this, tag);
            transaction.commitAllowingStateLoss(); // FIXME hacky and unpredictable workaround
        }
        return AlertDialogFragment.this;
    }

    @Override
    public int show(FragmentTransaction transaction, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    @Override
    public void show(FragmentManager manager, String tag) {
        throw new NoSuchMethodError("Please use AlertDialogFragment.show()!");
    }

    protected ParcelableOnClickListener createParcelableOnClickListener(AlertDialogFragment.OnClickListener onClickListener) {
        if (onClickListener == null) {
            return null;
        }

        return new ParcelableOnClickListener() {
            @Override
            public void onClick(AlertDialogFragment dialogFragment, int which) {
                onClickListener.onClick(dialogFragment, which);
            }
        };
    }

    /**
     * Parcelable OnClickListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnClickListener extends ResultReceiver implements AlertDialogFragment.OnClickListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnClickListener() {
            super(null);
        }

        @Override
        public abstract void onClick(AlertDialogFragment dialogFragment, int which);
    }

    /**
     * Parcelable OnDismissListener (can be remembered on screen rotation)
     */
    public abstract static class ParcelableOnDismissListener extends ResultReceiver implements AlertDialogFragment.OnDismissListener {
        public static final Creator<ResultReceiver> CREATOR = ResultReceiver.CREATOR;

        ParcelableOnDismissListener() {
            super(null);
        }

        @Override
        public abstract void onDismiss(AlertDialogFragment dialogFragment);
    }


    // =============================================================================================
    // endregion
}

ВИКОРИСТАННЯ

// showing a normal alert dialog with state loss on configuration changes (like device rotation)
new AlertDialog.Builder(getActivity())
        .setTitle("Are you sure? (1)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

// showing a dialog fragment using the helper class with no state loss on configuration changes
new AlertDialogFragment.builder(getActivity())
        .setTitle("Are you sure? (2)")
        .setMessage("Do you really want to do this?")
        .setPositiveButton("Yes", (dialog, which) -> Toast.makeText(getContext(), "Yes clicked", Toast.LENGTH_SHORT).show())
        .setNegativeButton("Cancel", null)
        .show();

Я публікую це тут не лише для того, щоб поділитися своїм рішенням, а й тому, що я хотів запитати у вас людей щодо вашої думки: чи легітимним чи певним є такий підхід?


3
Це дуже цікава ідея, але я не думаю, що дизайн API працює. Якщо ви передаєте OnClickListener на setPositiveButton (), коли пристрій повертається і фрагмент відтворюється з аргументів Bundle, OnClickListeners не буде належним чином відтворений з Parcelable. Основна проблема полягає в тому, що ви не можете відтворити слухача під час обертання, але інтерфейс API (який займає інтерфейси) вимагає цього. Я б хотів, щоб це було не так (як мені подобається ідея).
Xargs

1
Хороша ідея, але як каже @Xargs, вона не працює. Слухачі, що передаються, не відтворюються правильно під час обертання.
Грем Борланд

Мої результати полягають у тому, що він фактично працює під час обертання та відновлення програми (наприклад, після переходу на головний екран), але не тоді, коли активність буде відновлена ​​після її повного знищення (тоді OnClickListeners справді втрачено). (Тестовано на Android 4.4.4 та Android 5.1.1)
flxapps

Я не перевірив цю точну реалізацію, але з того, що я перевірив, слухач, що розширює, перейшов у пакет фрагментів, викликається правильно при відтворенні. Я поняття не маю, чому, але, здається, працює.
Саад Фарук

@flxapps, якщо у власному вигляді переглядати, як можна отримати уявлення про дитину та змінити їх властивості або застосувати слухачів? У вашому класі ви не повертаєте жодного екземпляра діалогу, і це може спричинити виняток, якщо хтось спробує отримати перегляди дітей
Zubair Rehman,

5

Можна запропонувати трохи спростити відповідь @ ashishduh:

public class AlertDialogFragment extends DialogFragment {
public static final String ARG_TITLE = "AlertDialog.Title";
public static final String ARG_MESSAGE = "AlertDialog.Message";

public static void showAlert(String title, String message, Fragment targetFragment) {
    DialogFragment dialog = new AlertDialogFragment();
    Bundle args = new Bundle();
    args.putString(ARG_TITLE, title);
    args.putString(ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(targetFragment, 0);
    dialog.show(targetFragment.getFragmentManager(), "tag");
}

public AlertDialogFragment() {}

@NonNull
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState)
{
    Bundle args = getArguments();
    String title = args.getString(ARG_TITLE, "");
    String message = args.getString(ARG_MESSAGE, "");

    return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .create();
}

Це усуває необхідність ознайомлення користувача (класу) з внутрішніми компонентами та робить використання дійсно простим:

AlertDialogFragment.showAlert(title, message, this);

PS У моєму випадку мені знадобився простий діалог попередження, щоб я створив це. Ви можете застосувати підхід до так / ні або будь-якого іншого типу, який вам потрібен.


1

Використовуйте діалогове вікно для простих діалогів так чи ні.

Коли вам потрібні більш складні представлення даних, у яких вам потрібно впоратися з життєвим циклом, таким як oncreate, запити дозволів, будь-яке переосмислення життєвого циклу, я б використав фрагмент діалогу. Таким чином, ви відокремлюєте дозволи та будь-який інший код, у якому потрібно діяти діалоговому вікні, не потребуючи спілкування з викликом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.