OnClickListener в диалоговой кнопке вызывается дважды при длительной обработке - PullRequest
0 голосов
/ 13 февраля 2012

У меня есть ошибка в моем приложении, она выглядит очень странно, но ее легко воспроизвести.

Попробуйте этот код для действия:

public    int    myIncrement = 0;

protected Dialog onCreateDialog(int i, Bundle args)
    {
        if (i == DIALOG_TEST_MY_BUG)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Test");

            builder.setNegativeButton("Test", new DialogInterface.OnClickListener()
            {
                public void onClick(DialogInterface dialog, int id)
                {
                    Log.i("Test", "<- myIncrement : " + myIncrement);
                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;
                    Log.i("Test", "-> myIncrement : " + myIncrement);
                }
            }
        }
    }

Когда вы показываете это диалоговое окно,все нормально.Когда вы нажимаете на кнопку «Тест», все в порядке.Журнал показывает:

<- myIncrement : 0
-> myIncrement : 1000000

Но если вы несколько раз нажмете кнопку «Тест», onClickListener будет вызываться 2 или более раз:

<- myIncrement : 0
-> myIncrement : 1000000
<- myIncrement : 1000000
-> myIncrement : 2000000...

Здесь этот пример простопозвольте вам понять мою проблему.Эквивалент

                    for (int i = 0; i < 1000000; i++)
                        myIncrement ++;

- это длительная обработка с записью файлов и изменением представления, а другая - с синхронизацией на сервере.Я перепробовал множество изменений, таких как изменение логического значения в методе onClick, но безуспешно.

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

Ответы [ 2 ]

1 голос
/ 01 марта 2012

Изменить на это:

private AlertDialog builder = null;
protected Dialog onCreateDialog(int i, Bundle args)
 {
     if (i == DIALOG_TEST_MY_BUG)
     {
         if(builder != null && builder.isShowing()
             return; // prevent multiple dialog instances
         builder = new AlertDialog.Builder(this);
         builder.setTitle("Test"); 
1 голос
/ 13 февраля 2012

Вы пытаетесь запустить долгосрочную задачу в потоке пользовательского интерфейса, что полностью запрещено. Это может привести к таким ошибкам, как эта и ANR, если задание длится дольше 5 секунд. Поэтому для любых длительных задач вы должны создать отдельный поток. Я бы рекомендовал использовать класс AsyncTask , поскольку его очень просто использовать и синхронизировать с потоком пользовательского интерфейса, чтобы показать пользователям, что ваше приложение не застряло. Надеюсь, это поможет.

...