Я разрабатываю приложение для Android в Java, которое отображает сетку японских символов кандзи с использованием Recyclerview с GridlayoutManager . Я использую библиотеку Android JetPack Paging3 для загрузки данных из локальной базы данных SQLite и библиотеки Androidx.recyclerview.selection, чтобы позволить пользователям выбирать элементы. Похоже, что это вызвано несоответствием данных между тем, что обеспечивает PagingDataAdapter, и тем, что Mayoutmanager ожидает во время прохода макета. Я также не могу воспроизвести эту проблему.
java.lang.IndexOutOfBoundsException:
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6821)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:6757)
...
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren (GridLayoutManager.java:182)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout (RecyclerView.java:4346)
public class KanjiList extends Fragment {
private KanjiListAdapter kanjiListAdapter;
private SelectionTracker selectionTracker;
private RecyclerView recyclerView;
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
// ... view binding
setupRecyclerView();
// Observe new PagingData from ViewModel
viewModel.getKanjiPagingData().observe(getViewLifecycleOwner(), kanjiPagingData ->
kanjiListAdapter.submitData(getViewLifecycleOwner().getLifecycle(), kanjiPagingData));
// This is called after some items in the database are modified
handleEvent(KanjiListEvent.AfterKanjiDisabled event) {
recyclerView.post(() -> {
selectionTracker.clearSelection();
kanjiListAdapter.refresh();
});
}
}
private void setupRecyclerView() {
kanjiListAdapter = new KanjiListAdapter(this);
recyclerView.setAdapter(kanjiListAdapter);
// Setup GridLayoutManager
int screenWidth = getResources().getDisplayMetrics().widthPixels;
int minColumnWidth = getResources().getDimensionPixelSize(R.dimen.kanji_tile_min_size);
int maxColumns = Math.max(5, screenWidth / minColumnWidth);
GridLayoutManager layoutManager = new GridLayoutManager(requireContext(), maxColumns);
recyclerView.setLayoutManager(layoutManager);
// Setup SelectionTracker
selectionTracker = new SelectionTracker.Builder(
"kanji_list",
recyclerView,
new KanjiStableIdKeyProvider(kanjiListAdapter),
new KanjiListDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()).build();
kanjiListAdapter.setSelectionTracker(selectionTracker);
}
}
< /code>
Что я попробовал < /h2>
Убедитесь, что все вызовы kanjilistadapter.refresh () завернуты внутри recyclerview.post. Как, например: < /li>
< /ol>
recyclerView.post(() -> {
selectionTracker.clearSelection();
kanjiListAdapter.refresh();
});
Что может вызвать эту десинхронизацию между PagingDataAdapter и состоянием макета Recyclerview ? Существует ли известная проблема при объединении Paging3 (с включенными заполнителями), SelectionTracker и признанием данных с помощью Adapter.refresh () , что может привести к этому конкретному типу IndexoutOfBoundSexception ? Любая помощь или альтернативная стратегии отладки будут высоко оценены.
Я разрабатываю приложение для Android в Java, которое отображает сетку японских символов кандзи с использованием Recyclerview с GridlayoutManager . Я использую библиотеку Android JetPack Paging3 для загрузки данных из локальной базы данных SQLite и библиотеки Androidx.recyclerview.selection, чтобы позволить пользователям выбирать элементы. Похоже, что это вызвано несоответствием данных между тем, что обеспечивает PagingDataAdapter, и тем, что Mayoutmanager ожидает во время прохода макета. Я также не могу воспроизвести эту проблему.[code]java.lang.IndexOutOfBoundsException: at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6821) at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition (RecyclerView.java:6757) ... at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren (GridLayoutManager.java:182) at androidx.recyclerview.widget.RecyclerView.dispatchLayout (RecyclerView.java:4346) [/code] [b] stack trace 2: [/b] [code]java.lang.IndexOutOfBoundsException: at androidx.recyclerview.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition (RecyclerView.java:6590) at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline (RecyclerView.java:6796) ... at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren (GridLayoutManager.java:182) at androidx.recyclerview.widget.RecyclerView.dispatchLayout (RecyclerView.java:4346) < /code> Вот соответствующий код для моей настройки: < /p> [b] 1. ViewModel [/b] public class KanjiListViewModel extends ViewModel {
private final KanjiRepository kanjiRepository; public final LiveData kanjiPagingData; private final MutableLiveData currentParameters = new MutableLiveData();
public void loadKanji(String sortOrder, String query) { ListDataParameters newParams = new ListDataParameters(query, sortOrder); if (!newParams.equals(currentParameters.getValue())) { currentParameters.setValue(newParams); } } } < /code> [b] 2. Pagingsource [/b] извлекает данные из репозитория.public class KanjiPagingSource extends ListenableFuturePagingSource {
private final KanjiRepository kanjiRepository; private final String query; private final String sortOrder; private final ListeningExecutorService executor;
public KanjiPagingSource(/*...constructors...*/) { /*...*/ }
@NonNull @Override public ListenableFuture loadFuture(@NonNull LoadParams loadParams) { final int pageNumber = loadParams.getKey() != null ? loadParams.getKey() : 0; final int pageSize = loadParams.getLoadSize();
return executor.submit(() -> { try { int offset = pageNumber * pageSize; List kanjiList; int totalCount;
@Nullable @Override public Integer getRefreshKey(@NonNull PagingState pagingState) { // Standard refresh key implementation Integer anchorPosition = pagingState.getAnchorPosition(); if (anchorPosition == null) return null; LoadResult.Page anchorPage = pagingState.closestPageToPosition(anchorPosition); if (anchorPage == null) return null; Integer prevKey = anchorPage.getPrevKey(); if (prevKey != null) return prevKey + 1; Integer nextKey = anchorPage.getNextKey(); if (nextKey != null) return nextKey - 1; return null; } } < /code> [b] 3. Адаптер [/b] public class KanjiListAdapter extends PagingDataAdapter {
private SelectionTracker selectionTracker;
public KanjiListAdapter(KanjiListAdapterListener listener) { super(new KanjiDiffCallback()); // ... }
public void setSelectionTracker(SelectionTracker selectionTracker) { this.selectionTracker = selectionTracker; }
@Override public void onBindViewHolder(@NonNull KanjiTileViewHolder holder, int position) { Kanji kanji = getItem(position); if (kanji != null) { // ... bind data boolean isSelected = selectionTracker.isSelected((long) kanji.getId()); holder.kanjiTileView.isSelected(isSelected); } else { // Placeholder view holder.kanjiTileView.setKanji(' '); } }
// ... ViewHolder and DiffUtil implementation } < /code> [b] 4. Fragment [/b] Фрагмент устанавливает Recyclerview [/code], SelectionTracker и наблюдает за PagingData . Он также содержит логику, чтобы обновить адаптер.[code]public class KanjiList extends Fragment {
// Observe new PagingData from ViewModel viewModel.getKanjiPagingData().observe(getViewLifecycleOwner(), kanjiPagingData -> kanjiListAdapter.submitData(getViewLifecycleOwner().getLifecycle(), kanjiPagingData));
// This is called after some items in the database are modified handleEvent(KanjiListEvent.AfterKanjiDisabled event) { recyclerView.post(() -> { selectionTracker.clearSelection(); kanjiListAdapter.refresh(); }); } }
private void setupRecyclerView() { kanjiListAdapter = new KanjiListAdapter(this); recyclerView.setAdapter(kanjiListAdapter);
// Setup GridLayoutManager int screenWidth = getResources().getDisplayMetrics().widthPixels; int minColumnWidth = getResources().getDimensionPixelSize(R.dimen.kanji_tile_min_size); int maxColumns = Math.max(5, screenWidth / minColumnWidth); GridLayoutManager layoutManager = new GridLayoutManager(requireContext(), maxColumns); recyclerView.setLayoutManager(layoutManager);
// Setup SelectionTracker selectionTracker = new SelectionTracker.Builder( "kanji_list", recyclerView, new KanjiStableIdKeyProvider(kanjiListAdapter), new KanjiListDetailsLookup(recyclerView), StorageStrategy.createLongStorage()).build();
kanjiListAdapter.setSelectionTracker(selectionTracker); } } < /code> Что я попробовал < /h2>
Убедитесь, что все вызовы kanjilistadapter.refresh () завернуты внутри recyclerview.post. Как, например: < /li> < /ol> recyclerView.post(() -> { selectionTracker.clearSelection(); kanjiListAdapter.refresh(); }); [/code] Что может вызвать эту десинхронизацию между PagingDataAdapter и состоянием макета Recyclerview ? Существует ли известная проблема при объединении Paging3 (с включенными заполнителями), SelectionTracker и признанием данных с помощью Adapter.refresh () , что может привести к этому конкретному типу IndexoutOfBoundSexception ? Любая помощь или альтернативная стратегии отладки будут высоко оценены.
Я разрабатываю экран чата, все сообщения сразу сохраняются в Room, а затем я получаю их через Paging3.
Моя проблема в том, что я не могу прокрутить вниз до последнего элемента. после отправки сообщения. Когда я пытаюсь использовать...
У меня есть RecyclerView внутри RecyclerView. Когда я запускаю просмотр, все в порядке. Но когда я обновляю свой RecyclerView (родительский), мое представление автоматически прокручивается до первого дочернего RecyclerView. Я не вижу элемента в...
У меня возникла проблема с реализацией функции onRowMoved в моем адаптере RecyclerView. Эта функция отвечает за управление перемещением строк в RecyclerView при перетаскивании элементов. Однако я столкнулся с ошибкой...
У меня возникла проблема с реализацией функции onRowMoved в моем адаптере RecyclerView. Эта функция отвечает за управление перемещением строк в RecyclerView при перетаскивании элементов. Однако я столкнулся с ошибкой...