Android - ListView повторяющихся событий
В моем приложении у меня есть ListView, поддерживаемый ArrayAdapter. В нем я обнаруживаю события в методе OnScrollListener#onScroll, чтобы найти конец списка. Я заметил, что на телефоне (MyTouch) и трекбол, и жест / касание прокручивают событие дважды. На эмуляторе я получаю такое же поведение с колесом прокрутки и прокруткой по клику и наркотику. Однако в эмуляторе, если я использую кнопку со стрелкой вниз для прокрутки, событие запускается только один раз.
Вот код:
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);
}
}
}
Как мне подавить или справиться с этим поведением? Мне нужно только одно событие и попытаться не возвращаться к глупым взломам, таким как булево поле.
Насколько я могу сказать - оба события имеют одинаковую трассировку стека
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]
PS Баг создан
PPS И закрыто с очень полезным ответом The trackball and the touch screen send several motion events very rapidly. This behavior is expected.
2 ответа
Так как хорошие люди из 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);
}
});
У меня также есть эта проблема с несколькими событиями запуска, пока я прокручивал ListView. Я намеревался загрузить больше ListItems в тот момент, когда я передавал пороговое значение. Тем не менее, это всегда приводило к множеству AsyncTasks, которые заполняли мой ListView быстрее, чем хотелось.
Я нашел хорошее решение в этом посте. В основном это включает проверку на логическое значение, хотя вам не нравится это решение. Я нахожу это также своего рода хакерским, но я не нашел другого решения, хотя.