2009-10-13 3 views
4

В моем приложении у меня есть ListView, поддерживаемый ArrayAdapter. В нем я обнаруживаю события в методе OnScrollListener # onScroll, чтобы найти конец списка. Я заметил, что по телефону (MyTouch) и трек-мяч, и жест/сенсорная прокрутка вызовут событие дважды. На эмуляторе я получаю такое же поведение со скроллинговым колесом и прокруткой кликов и наркотиков. Однако в эмуляторе, если я использую кнопку со стрелкой вниз для прокрутки, событие запускается только один раз.Android - ListView duplicate events

Вот код:

this.view.setOnScrollListener(new OnScrollListener() { 
    @Override 
    public void onScroll(final AbsListView view, final int first, 
           final int visible, final int total) { 
     // detect if last item is visible 
     if (visible < total && (first + visible == total)) { 
      Log.d("OnScrollListener - end of list", "fvi: " + 
       first + ", vic: " + visible + ", tic: " + total); 
      // this line gets called twice 
      onLastListItemDisplayed(total, visible); 
     } 
    } 
} 

Как подавить или обрабатывать такое поведение? Мне нужно только одно событие и пытаться не возвращаться к таким глупым хакам, как логическое поле.

Насколько я могу сказать - оба события имеют одинаковые StackTrace

Thread [<3> main] (Suspended (breakpoint at line 116 in SearchResultsView$4)) 
SearchResultsView$4.onScroll(AbsListView, int, int, int) line: 116 
ListView(AbsListView).invokeOnItemScrollListener() line: 655 
ListView.arrowScrollImpl(int) line: 2256 
ListView.arrowScroll(int) line: 2172 
ListView.commonKey(int, int, KeyEvent) line: 1977 
ListView.onKeyMultiple(int, int, KeyEvent) line: 1929 
KeyEvent.dispatch(KeyEvent$Callback) line: 899 
ListView(View).dispatchKeyEvent(KeyEvent) line: 3647 
ListView(ViewGroup).dispatchKeyEvent(KeyEvent) line: 744 
ListView.dispatchKeyEvent(KeyEvent) line: 1909 
FrameLayout(ViewGroup).dispatchKeyEvent(KeyEvent) line: 746 
LinearLayout(ViewGroup).dispatchKeyEvent(KeyEvent) line: 746 
PhoneWindow$DecorView(ViewGroup).dispatchKeyEvent(KeyEvent) line: 746 
PhoneWindow$DecorView.superDispatchKeyEvent(KeyEvent) line: 1708 
PhoneWindow.superDispatchKeyEvent(KeyEvent) line: 1197 
SearchResultsView(Activity).dispatchKeyEvent(KeyEvent) line: 1967 
PhoneWindow$DecorView.dispatchKeyEvent(KeyEvent) line: 1684 
ViewRoot.deliverKeyEventToViewHierarchy(KeyEvent, boolean) line: 2329 
ViewRoot.handleFinishedEvent(int, boolean) line: 2299 
ViewRoot.handleMessage(Message) line: 1621 
ViewRoot(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 123 
ActivityThread.main(String[]) line: 4203 
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method] 
Method.invoke(Object, Object...) line: 521 
ZygoteInit$MethodAndArgsCaller.run() line: 791 
ZygoteInit.main(String[]) line: 549 
NativeStart.main(String[]) line: not available [native method] 

P.S. Bug is created

P.P.S. И закрыл очень полезный ответ The trackball and the touch screen send several motion events very rapidly. This behavior is expected.

+0

Я помню, как бежал через это тоже. Никогда не нашел решения. Удачи. –

+0

Я отправил ошибку на сайте отслеживания ошибок Android, посмотрю, могут ли они хотя бы прокомментировать это. – Bostone

ответ

4

Поскольку хорошие люди Google говорят, что это as intended, вот уродливый жестокий способ справиться с этой проблемой, которая работает на меня. В основном предположение состоит в том, что по мере выпуска событий я сравниваю последний сохраненный индекс первого элемента с тем, который передается в вызове onScroll. Я только процесс событий, если они не совпадают:

this.view.setOnScrollListener(new OnScrollListener() { 
     private int lastSavedFirst = -1; 
     @Override 
     public void onScroll(final AbsListView view, final int first, final int visible, final int total) { 
      // detect if last item is visible 
      if (visible < total && (first + visible == total)) { 
       // only process first event 
       if (first != lastSavedFirst) { 
        lastSavedFirst = first; 
        Log.d("OnScrollListener - end of list", "fvi: " + first + ", vic: " + visible + ", tic: " 
          + total); 
        onLastListItemDisplayed(total, visible); 
       } 
      } 
     } 

     @Override 
     public void onScrollStateChanged(final AbsListView view, final int scrollState) { 
      // Log.d("OnScrollListener", "state: " + scrollState); 
     } 
    }); 
+0

Большое спасибо. , , –

0

У меня тоже эту проблему с несколько событий обжига, когда я прокрутке ListView. Я намеревался загрузить больше ListItems в тот момент, когда я передавал стоимость трески. Тем не менее, это всегда приводило к появлению нескольких названных AsyncTasks, которые заполняли мой ListView быстрее, чем хотелось.

Я нашел хорошее решение в this blogpost. Это в основном включает проверку булевых, хотя вам не нравится это решение. Я нахожу это также своего рода хаккой, но я не придумал другого решения.