Android中如何为Firebase Recycler View项添加按钮并获取对应数据?
先来说说第一个问题:点击DELETE按钮时怎么获取对应列表项的任务数据,进而删除指定任务。其实核心就是让按钮点击时能关联到当前项的任务对象,这样就能拿到它在数据库里的UUID节点了。
一、点击DELETE按钮获取任务数据并删除
1. 先确保Adapter持有任务数据集
首先你的RecyclerView Adapter里得维护一个任务列表,比如用List<Task>来存,同时要拿到Firebase数据库的引用和当前用户ID。假设你的任务模型类是Task,里面有taskName、taskId(对应数据库里的随机UUID)这些字段:
private List<Task> mTaskList; private DatabaseReference mDbRef; private String mCurrentUserId; // 就是你说的vfPvsk...那个用户ID // 构造方法初始化 public TaskAdapter(List<Task> taskList, DatabaseReference dbRef, String userId) { mTaskList = taskList; mDbRef = dbRef; mCurrentUserId = userId; }
2. 在ViewHolder里给按钮绑定点击事件
在你的ViewHolder类中,给DELETE按钮设置点击监听,点击时先获取当前项的位置,再从数据集里拿到对应的Task对象,这样就能拿到它的taskId(数据库节点ID),然后去Firebase删除这个节点:
public class TaskViewHolder extends RecyclerView.ViewHolder { Button deleteBtn; TextView taskNameTv; ImageView taskImg; public TaskViewHolder(View itemView) { super(itemView); deleteBtn = itemView.findViewById(R.id.delete_btn); taskNameTv = itemView.findViewById(R.id.task_name); taskImg = itemView.findViewById(R.id.task_image); deleteBtn.setOnClickListener(v -> { // 获取当前点击项的位置,避免无效点击 int pos = getAdapterPosition(); if (pos != RecyclerView.NO_POSITION) { Task targetTask = mTaskList.get(pos); String taskId = targetTask.getTaskId(); // 这就是数据库里的773f...那个节点ID // 先弹Toast确认一下 Toast.makeText(v.getContext(), "准备删除任务:" + targetTask.getTaskName(), Toast.LENGTH_SHORT).show(); // 去Firebase删除对应节点 mDbRef.child(mCurrentUserId).child(taskId).removeValue() .addOnSuccessListener(aVoid -> { // 删除成功后,记得从数据集里移除该项并通知Adapter更新UI mTaskList.remove(pos); notifyItemRemoved(pos); Toast.makeText(v.getContext(), "任务删除成功!", Toast.LENGTH_SHORT).show(); }) .addOnFailureListener(e -> { Toast.makeText(v.getContext(), "删除失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); }); } }); } }
关键提醒:读取数据时要把节点ID存到Task对象里
从Firebase读取任务数据的时候,一定要把每个任务的节点UUID(也就是taskSnapshot.getKey())赋值给Task对象的taskId字段,不然点击时拿不到对应的节点ID:
mDbRef.child(mCurrentUserId).addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { mTaskList.clear(); for (DataSnapshot taskSnap : snapshot.getChildren()) { Task task = taskSnap.getValue(Task.class); task.setTaskId(taskSnap.getKey()); // 把数据库节点ID存进Task对象 mTaskList.add(task); } notifyDataSetChanged(); } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理读取失败的情况 Toast.makeText(context, "读取数据失败:" + error.getMessage(), Toast.LENGTH_SHORT).show(); } });
二、缩小RecyclerView列表项中的图片
缩小图片有几种简单的方法,根据你的需求选就行:
方法1:布局里直接固定ImageView尺寸
最直接的就是在列表项的布局文件中,给ImageView设置固定的宽高,比如:
<ImageView android:id="@+id/task_image" android:layout_width="70dp" android:layout_height="70dp" android:scaleType="centerCrop" /> <!-- centerCrop可以让图片保持比例填满ImageView,不会变形 -->
方法2:用Glide动态调整大小(推荐)
如果你的图片是从网络加载的(比如Firebase Storage里的图片),用Glide不仅能调整大小,还能做缓存、占位图,体验更好。
首先在app/build.gradle里添加Glide依赖:
dependencies { implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' }
然后在ViewHolder中加载图片时指定大小:
// 假设你的Task对象里有getImageUrl()方法返回图片地址 Glide.with(itemView.getContext()) .load(targetTask.getImageUrl()) .override(70, 70) // 这里的单位是px,要是想适配不同屏幕,转成dp更稳妥 .centerCrop() .into(taskImg);
如果要适配不同屏幕,写个dp转px的工具方法:
private int dpToPx(Context context, int dp) { return (int) (dp * context.getResources().getDisplayMetrics().density); }
然后调用的时候换成:
Glide.with(itemView.getContext()) .load(targetTask.getImageUrl()) .override(dpToPx(itemView.getContext(), 70), dpToPx(itemView.getContext(), 70)) .centerCrop() .into(taskImg);
方法3:用scaleType让图片自适应
要是不想固定大小,也可以通过scaleType属性让图片自动缩小到ImageView的范围内,比如android:scaleType="fitCenter"会保持图片比例,缩放到ImageView能容纳的大小;fitXY会拉伸填充,但可能会让图片变形,根据需求选就行。
内容的提问来源于stack exchange,提问作者jonb

