Как проверить, отображается ли пользовательский DialogFragment?

1) В моем приложении пользователь может получать много уведомлений от FCM
2) Если у пользователя открыто приложение, ему нужно отобразить пользовательский DialogFragment
3) Если DialogFragment уже отображается, то при следующем приходе уведомления необходимо запретить повторное отображение этого DialogFragment
4) Мой код диалога:

public final class NotificationEventDialog extends DialogFragment implements DialogInterface.OnKeyListener, View.OnClickListener {
    private Activity mCurrentActivity;
    private NotificationEventDialogListener mNotificationEventDialogListener;

    public interface NotificationEventDialogListener {
        void showEvent();
    }

    public NotificationEventDialog() {
    }

    public static NotificationEventDialog newInstance() {
        NotificationEventDialog notificationEventDialog = new NotificationEventDialog();
        notificationEventDialog.setCancelable(false);
        return notificationEventDialog;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mCurrentActivity = (Activity)context;
        try {
            mNotificationEventDialogListener = (NotificationEventDialogListener) mCurrentActivity;
        } catch (ClassCastException e) {
            throw new ClassCastException(mCurrentActivity.toString() + " must implemented NotificationEventDialogListener");
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        LayoutInflater inflater = LayoutInflater.from(mCurrentActivity);
        @SuppressLint("InflateParams") View view = inflater.inflate(R.layout.dialog_notification_event, null);

        Button btnNotificationEventYes = view.findViewById(R.id.notification_event_dialog_yes);
        btnNotificationEventYes.setOnClickListener(this);

        Button btnNotificationEventNo = view.findViewById(R.id.notification_event_dialog_no);
        btnNotificationEventNo.setOnClickListener(this);

        AlertDialog.Builder builder = new AlertDialog.Builder(mCurrentActivity);
        builder.setView(view);

        return builder.create();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (getDialog() != null && getDialog().getWindow() != null) {
            getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            getDialog().setOnKeyListener(this);
        }
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCurrentActivity = null;
        mNotificationEventDialogListener = null;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.notification_event_dialog_yes:
                dismiss();
                mNotificationEventDialogListener.showEvent();
                break;
            case R.id.notification_event_dialog_no:
                dismiss();
                break;
        }
    }

    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK)) {
            dismiss();
            return true;
        } else return false;
    }
} 

5) Каждый раз, когда я получаю уведомление от FCM, я создаю диалоговое окно:

DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();  
notificationEventDialog.show(getSupportFragmentManager(), "");  

6) Как проверить, отображается ли уже DialogFragment? Каждый раз я создаю новый объект этого окна и не могу сделать его как Singleton, т.к. это приводит к утечке памяти.

Нашел ответ, в котором человек предлагает использовать слабые ссылки для решения этой проблемы:

Также вы можете сохранить слабую ссылку на показанный диалог в этом классе singletone. Используя такой метод, вы можете определить, отображается ли ваш диалог в данный момент или нет.

Был и такой ответ:

Я предлагаю сохранить ссылку на диалог в одном экземпляре класса. В этом случае создайте метод sureShowDialog (контекстный контекст). Этот метод будет проверять текущий показанный диалог или нет. Если да, вы можете показать диалог. В другом casr вы можете передать новые данные в диалог.

Но, честно говоря, не совсем понимаю, как использовать эти советы на практике. Пожалуйста, можете помочь с этой реализацией или предложить другой способ? Заранее спасибо.


person Tomas    schedule 29.01.2019    source источник


Ответы (2)


Вы можете использовать:

    val ft: FragmentTransaction = fragmentManager!!.beginTransaction()
    val prev: Fragment? = fragmentManager!!.findFragmentByTag("typeDialog")

    if (prev == null) {
        val fm = fragmentManager
        val courseTypeListDialogFragment =
            CourseTypeListDialogFragment()
        courseTypeListDialogFragment.isCancelable = false
        courseTypeListDialogFragment.setStyle(
            DialogFragment.STYLE_NO_TITLE,
            0
        )
        courseTypeListDialogFragment.setTargetFragment(this, 1)
        if (fm != null) {
            courseTypeListDialogFragment.show(ft, "typeDialog")
        }
    }
person jo jo    schedule 18.03.2020

Вы можете проверить, отображается ли фрагмент диалога, вызвав isAdded ( ) внутри DialogFragment или

DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();
notificationEventDialog.isAdded()

от деятельности

Он вернет true, если фрагмент добавлен в действие, в случае фрагмента диалога - отображается.

Вы можете сохранить дату последнего показанного фрагмента диалога, поставив System.currentTimeMillis() в SharedPreferences

Я думаю, у вас есть идея.

person Serhii Pokrovskyi    schedule 29.01.2019
comment
Сомневаюсь в вашей идее с методом isAdded, т.к. NotificationEventDialog.newInstance() создаёт НОВЫЙ объект и соответственно - новый DialogFragment. И каждый раз я буду получать, что мой DialogFragment добавлен. - person Tomas; 29.01.2019
comment
Так что, пожалуйста, дайте разъяснение. Вам нужно отобразить DialogFragment это сообщение от FCM? И вам нужно знать, отображал ли фрагмент диалога это конкретное сообщение или нет? - person Serhii Pokrovskyi; 31.01.2019