Есть метод, в котором обрабатываю нажатие по элементу:
override fun onListItemClick(itemIndex: Int, itemCode: String) {
presenter.onItemClick(adapter.getItem(itemIndex))
}
Но проблема в том, что пользователь как то умудрился нажать на -1 элемент. Что выдало мне ошибку:
"backtrace" => "[\"java.lang.ArrayIndexOutOfBoundsException: length\u003d25; index\u003d-1\",\" at java.util.ArrayList.get(ArrayList.java:310)\",\" at com.project.android.features.common.base_list.AbstractListAdapter.getItem(AbstractListAdapter.kt:20)\",\" at com.project.android.features.categories.selector.CategorySelectDialog.onListItemClick(CategorySelectDialog.kt:59)\",\" at com.project.android.features.categories.selector.CategorySelectItemViewHolder$1.onClick(CategorySelectItemViewHolder.kt:32)\",\" at android.view.View.performClick(View.java:4856)\",\" at android.view.View$PerformClick.run(View.java:19956)\",\" at android.os.Handler.handleCallback(Handler.java:739)\",\" at android.os.Handler.dispatchMessage(Handler.java:95)\",\" at android.os.Looper.loop(Looper.java:211)\",\" at android.app.ActivityThread.main(ActivityThread.java:5371)\",\" at java.lang.reflect.Method.invoke(Native Method)\",\" at java.lang.reflect.Method.invoke(Method.java:372)\",\" at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:945)\",\" at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:740)\"]",
Как такое возможно? И как исключить момент нажатия пользователя на -1 элементе списка?
В одном из мест где использую данный метод:
titleView.setOnClickListener { listener?.onListItemClick(adapterPosition, "") }
Перешёл к реализации adapterPosition и увидел следующее:
/** * Returns the Adapter position of the item represented by this ViewHolder. *
* Note that this might be different than the {@link #getLayoutPosition()} if there are * pending adapter updates but a new layout pass has not happened yet. *
* RecyclerView does not handle any adapter updates until the next layout traversal. This * may create temporary inconsistencies between what user sees on the screen and what * adapter contents have. This inconsistency is not important since it will be less than * 16ms but it might be a problem if you want to use ViewHolder position to access the * adapter. Sometimes, you may need to get the exact adapter position to do * some actions in response to user events. In that case, you should use this method which * will calculate the Adapter position of the ViewHolder. *
* Note that if you've called {@link RecyclerView.Adapter#notifyDataSetChanged()}, until the * next layout pass, the return value of this method will be {@link #NO_POSITION}. * * @return The adapter position of the item if it still exists in the adapter. * {@link RecyclerView#NO_POSITION} if item has been removed from the adapter, * {@link RecyclerView.Adapter#notifyDataSetChanged()} has been called after the last * layout pass or the ViewHolder has already been recycled. */
Возможно где то тут кроется проблема? Так как именно в этом методе возвращается -1.
public final int getAdapterPosition() {
if (mOwnerRecyclerView == null) {
return NO_POSITION;
}
return mOwnerRecyclerView.getAdapterPositionFor(this);
}
При получении позиции в списке адаптера через метод getAdapterPosition()
, возможны ситуации, когда адаптер RecyclerView
возвращает значение NO_POSITION (значение константы -1), например, когда клик по айтему произошел во время обновления списка. Такую ситуацию нужно обрабатывать отдельно, например так (совершать действия по клику на айтеме только когда позиция не равна NO_POSITION):
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
switch (v.getId()) {
case R.id.menu_button:
//
break;
case R.id.card:
//
break;
}
}
}
или использовать метод getLayoutPosition()
, который тоже имеет свои недостатки (позиция не всегда соответствует действительной при определенных обстоятельствах).
Подробнее смотрите офф.документацию (раздел Positions in RecyclerView)
Я бы до выявления проблемы, посоветовал бы обернуть метод в try-catch:
override fun onListItemClick(itemIndex: Int, itemCode: String) {
try {
presenter.onItemClick(adapter.getItem(itemIndex))
} catch (e: Exception) { }
}
Вообще в блок catch неплохо бы выводить логи об ошибке, что то вроде:
e.log()
А уже в нём реализуете метод получения ошибки(примерно как то так).
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Столкнулся со следующей проблемой: при попытке нарисовать что-либо на OpenGL после его первой прорисовке ничего не рисуетсяПробовал и glSurfaceView
ЗдравствуйтеИмеется TextView, которая будет зажата с двух сторон другими элементами