Android: эмулятор Android 4.1 Вызов onDateSet дважды из диалогового окна DatePicker

Мое приложение отлично работало на моем эмуляторе Android 2.2. Затем я решил протестировать эмулятор Android 4.1. DatePickerDialog выглядит немного по-другому и по какой-то причине, когда я нажимаю "Готово", прослушиватель onDateSet() дважды вызывается и вызывает проблемы в моем приложении.

Я знаю это, потому что журнал, показанный ниже в коде, печатается дважды, когда я нажимаю "Готово"

mDateSetListener = new DatePickerDialog.OnDateSetListener() {
    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
            Log.v("onDateSet", "ENTERED");
            //rest of code...
    }};

Android 2.2 DatePicker

Working Android 2.2 DatePicker

Android 4.1 DatePicker

Not Working Android 4.1 DatePicker

Ответ 1

Попробуйте установить логическое значение для проверки двойного огня в том же диалоговом окне. Нечто похожее на:

Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_YEAR, 1);
final DatePickerDialog dateDialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener() {
    boolean fired = false;
    public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
        Log.i("PEW PEW", "Double fire check");
        if (fired) {
            Log.i("PEW PEW", "Double fire occured. Silently-ish returning");
            return;
        } else {
            //first time fired
            fired = true;
        }
        //Normal date picking logic goes here
    }
}, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH));
dateDialog.show();

Эта проблема с двойным огнем также происходит с onTimeSet TimePickerDialog, и эта проверка также работает для них.

Ответ 2

Согласно Ankur Chaudhary блестящий ответ по аналогичной проблеме TimePickerDialog, если мы проверили внутри onDateSet, если данное представление isShown() или нет, оно будет решить всю проблему с минимальными усилиями, без необходимости расширять сборщик или проверять некоторые отвратительные флаги, идущие вокруг кода или даже проверять версию ОС, просто выполните следующие действия:

public void onDateSet(DatePicker view, int year, int month, int day) {
    if (view.isShown()) {
        // read the date here :)
    }
}

и, конечно же, это можно сделать для onTimeSet согласно ответу Ankur

Ответ 3

Я думаю, что это связано, я начал тестировать на 4.1 сегодня и обнаружил, что некоторые события javascript, похоже, срабатывают дважды. В данный момент в основном нажмите. Странно, если я добавлю предупреждение, он "иногда" срабатывает один раз. Поведение странно непоследовательно.

События javascript реагируют таким образом на Android 4.1. iPhone кажется прекрасным, как и все предыдущие версии Android, которые я пробовал до сих пор (включая 4.0.x).

Похоже на ошибку в браузере или на то, как он обрабатывает javascript для меня, но это просто предположение.

Ответ 4

Повторить: это подтвержденная ошибка в Android. Два метода обхода уже предложены, сохраняя состояние в переменной (экземпляре) или запрашивая диалоговое окно, если оно isShown(). Но isShown() кажется ненадежным (например, этот ответ), и сохранение состояния становится беспорядочным, если вы хотите повторно показать диалог.
Лучшим решением является сохранение состояния внутри самого диалогового окна:

public void onDateSet(DatePicker picker, int year, int monthOfYear, int dayOfMonth) {
    if (picker.getTag() == null) {
        picker.setTag("TAGGED");
        // Only gets called once per Dialog
    }
}

Он чист и эффективен.