{"record":{"id":"45324886cd183b44","repo":"Tencent/QMUI_Android","slug":"error","errorCode":null,"errorMessage":"替换数据不存在","messagePattern":"替换数据不存在","errorType":"exception","errorClass":"IllegalAccessException","httpStatus":null,"severity":"error","filePath":"qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIItemViewsAdapter.java","lineNumber":138,"sourceCode":"        mParentView.requestLayout();\n\n    }\n\n    public T getItem(int position) {\n        if (mItemData == null) {\n            return null;\n        }\n        if (position < 0 || position >= mItemData.size()) {\n            return null;\n        }\n        return mItemData.get(position);\n    }\n\n    public void replaceItem(int position, T data) throws IllegalAccessException {\n        if (position < mItemData.size() && position >= 0) {\n            mItemData.set(position, data);\n        } else {\n            throw new IllegalAccessException(\"替换数据不存在\");\n        }\n\n    }\n\n    protected abstract void bind(T item, V view, int position);\n\n    public List<V> getViews() {\n        return mViews;\n    }\n\n    public int getSize() {\n        if (mItemData == null) {\n            return 0;\n        }\n        return mItemData.size();\n    }\n}\n","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/Tencent/QMUI_Android/blob/026e7d486677d6593a96689cd590ec3561176717/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIItemViewsAdapter.java#L120-L156","documentation":"QMUIItemViewsAdapter.replaceItem validates that the given position is within 0..size-1 of mItemData; otherwise it throws IllegalAccessException with the Chinese message meaning 'replacement data does not exist'. The odd exception type is a legacy API choice, but the condition is simply an out-of-range index.","triggerScenarios":"Calling replaceItem(position, data) with a negative position or a position >= mItemData.size(), e.g. replacing item at an index that was removed, or using a RecyclerView adapter position after data was cleared.","commonSituations":"Updating a tab/badge item after data shrink, off-by-one when using size as index, or stale positions captured before the adapter's data changed.","solutions":["Validate position: if (position >= 0 && position < adapter.getItemData().size()) before calling replaceItem.","Compute the index from a stable identifier rather than a stale stored index.","Clamp or ignore the update when the list shrank, and refresh the adapter instead.","Catch IllegalAccessException around replaceItem as a guard if the data size can change concurrently."],"exampleFix":"// before\nviewsAdapter.replaceItem(position, newData); // may throw if position stale\n// after\nif (position >= 0 && position < viewsAdapter.getItemData().size()) {\n    viewsAdapter.replaceItem(position, newData);\n}","handlingStrategy":"validation","validationCode":"if (position < 0 || position >= adapter.getItemData().size()) return;\nadapter.replaceItem(position, data);","typeGuard":null,"tryCatchPattern":"try {\n    adapter.replaceItem(position, data);\n} catch (IllegalAccessException e) {\n    Log.w(TAG, \"stale position \" + position + \" for replaceItem\", e);\n}","preventionTips":["Always bounds-check the position against the current data size before replaceItem.","Avoid caching adapter positions across data mutations; look up by stable id.","After data changes, refresh/rebind instead of replacing at stale indices.","Watch off-by-one: valid positions are 0..size-1, never size."],"tags":["android","qmui","index-out-of-bounds","adapter"],"backgroundTag":"index-out-of-range","analyzedSha":"026e7d486677d6593a96689cd590ec3561176717","analyzedAt":"2026-09-06T13:32:24.816Z","contentChangedAt":"2026-09-06T13:32:24.816Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}