基于选中位置裁剪ArrayList 解决跨Activity传输事务过大异常
解决ParcelableArrayList传递过大导致的TransactionTooLargeException问题
这个问题我之前也碰到过,Binder的事务大小限制(通常在1MB左右)确实挺头疼的,尤其是处理大量媒体项的时候。咱们直接来看怎么实现你要的「超过1000项就裁剪为选中位置前后各25个」的逻辑:
核心思路
当原媒体列表大小超过1000时,计算出需要保留的索引范围:
- 起始索引:不能小于0,取
选中位置-25和0的最大值 - 结束索引:不能超过列表最后一个元素的索引,取
选中位置+25和列表长度-1的最大值 - 截取这个范围内的子列表,转成新的ArrayList后再传递,同时别忘了传递选中位置在新列表中的相对索引(避免目标Activity定位出错)
具体代码实现
在准备跳转的Activity中:
// 假设你已经从RecyclerView拿到了原媒体列表和选中位置 ArrayList<MediaItem> originalMediaList = ...; int selectedPos = ...; Intent intent = new Intent(this, TargetActivity.class); if (originalMediaList.size() > 1000) { // 计算裁剪的起始和结束索引 int startIndex = Math.max(0, selectedPos - 25); int endIndex = Math.min(originalMediaList.size() - 1, selectedPos + 25); // 截取子列表并转为新的ArrayList(subList返回的是原列表的视图,转成新集合避免原列表修改影响) ArrayList<MediaItem> croppedMediaList = new ArrayList<>(originalMediaList.subList(startIndex, endIndex + 1)); // 计算选中位置在新列表中的相对索引 int newSelectedPos = selectedPos - startIndex; // 传递裁剪后的列表和新的选中位置 intent.putParcelableArrayListExtra("CROPPED_MEDIA_LIST", croppedMediaList); intent.putExtra("SELECTED_POS_IN_CROPPED", newSelectedPos); } else { // 列表大小未超过限制,直接传递原列表和原位置 intent.putParcelableArrayListExtra("CROPPED_MEDIA_LIST", originalMediaList); intent.putExtra("SELECTED_POS_IN_CROPPED", selectedPos); } startActivity(intent);
在目标Activity中接收数据:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_target); ArrayList<MediaItem> mediaList = getIntent().getParcelableArrayListExtra("CROPPED_MEDIA_LIST"); int selectedPos = getIntent().getIntExtra("SELECTED_POS_IN_CROPPED", 0); // 后续用这两个数据做业务逻辑即可,比如定位到选中项 }
边界情况说明
- 当选中位置靠近列表开头(比如
selectedPos=10):起始索引会被限制为0,最终保留0到35的元素 - 当选中位置靠近列表末尾(比如原列表有2000项,
selectedPos=1990):结束索引会被限制为1999,最终保留1965到1999的元素 - 如果你的
MediaItem本身携带了大量数据(比如大图字节数组),即使裁剪到51项仍可能触发异常,这种情况建议改用全局单例、ViewModel或ContentProvider来共享数据,避免通过Intent传递大对象
内容的提问来源于stack exchange,提问作者BigDX
相关产品推荐
相关产品推荐

