如何在ItemView的OnClickListener中通过Launcher从相册获取图片
解决方案
1. 在宿主Activity中创建ActivityResultLauncher
先在承载RecyclerView的Activity里定义图片选择Launcher,同时通过回调接口实现选中图片后更新对应Item的逻辑:
// 定义回调接口,用于通知Adapter更新指定位置的Item public interface OnImageSelectedListener { void onImageSelected(int position, Uri imageUri); } private ActivityResultLauncher<String> pickImageLauncher; private OnImageSelectedListener imageSelectedListener; private int currentSelectedPosition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化图片选择Launcher pickImageLauncher = registerForActivityResult(new ActivityResultContracts.GetContent(), result -> { if (result != null && imageSelectedListener != null) { imageSelectedListener.onImageSelected(currentSelectedPosition, result); } }); } // 给Adapter提供设置回调的入口 public void setImageSelectedListener(OnImageSelectedListener listener) { this.imageSelectedListener = listener; } // 记录当前点击的Item位置 public void setCurrentSelectedPosition(int position) { this.currentSelectedPosition = position; }
2. 让Adapter与宿主交互触发Launcher并更新Item
在Adapter中持有宿主的弱引用(避免内存泄漏),点击Item时通知宿主启动图片选择器,接收回调后更新对应Item:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private List<ItemData> dataList; private WeakReference<MainActivity> hostActivityRef; public MyAdapter(List<ItemData> dataList, MainActivity hostActivity) { this.dataList = dataList; this.hostActivityRef = new WeakReference<>(hostActivity); // 设置图片选中后的回调逻辑 hostActivity.setImageSelectedListener((position, imageUri) -> { dataList.get(position).setImageUri(imageUri); notifyItemChanged(position); // 仅刷新选中的Item,提升性能 }); } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { ItemData item = dataList.get(position); // 加载已有的图片(示例用Glide,可替换为其他图片加载库) if (item.getImageUri() != null) { Glide.with(holder.itemView.getContext()) .load(item.getImageUri()) .into(holder.itemImage); } holder.itemView.setOnClickListener(v -> { MainActivity hostActivity = hostActivityRef.get(); if (hostActivity != null) { hostActivity.setCurrentSelectedPosition(position); hostActivity.pickImageLauncher.launch("image/*"); } }); } static class MyViewHolder extends RecyclerView.ViewHolder { ImageView itemImage; public MyViewHolder(@NonNull View itemView) { super(itemView); itemImage = itemView.findViewById(R.id.item_image); } } }
3. 关键注意事项
- 若宿主是Fragment,逻辑完全一致,只需在Fragment中注册Launcher并传递回调即可。
- 必须用
WeakReference包装宿主引用,防止Activity销毁后Adapter持有强引用导致内存泄漏。 - 图片加载建议使用Glide、Picasso等成熟库,简化Uri到ImageView的绑定逻辑。
内容的提问来源于stack exchange,提问作者codingsheep
相关产品推荐
相关产品推荐

