You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView筛选后点击项触发原列表位置事件的问题求助

Fixing RecyclerView Click Mismatch After Adding Filter Functionality

Hey there, let's break down what's causing this issue and fix it step by step!

The Root Problem

Your bug comes from two key mistakes:

  1. You're overwriting your original full data list (devicelist = filteredList; in the filter method) — this means you lose all reference to the original positions of items.
  2. You're using the filtered list's position to generate childpos for database operations. When you filter to show only "B" (originally at position 1), the filtered list's position is 0, so you end up modifying the first item in the original list (A) instead of B.

Solution 1: Keep Original List & Map Filtered Items to Original Positions

First, preserve your original full dataset so you never lose track of item positions.

Step 1: Maintain a Separate Original List

Add a class-level variable to hold your unfiltered data:

// Declare this in your Activity class
private ArrayList<Devices> originalDeviceList;

Initialize it when you first load your data (e.g., in onCreate):

// Assuming devicelist is initially populated with all items
originalDeviceList = new ArrayList<>(devicelist);

Step 2: Fix the Filter Method

Don't overwrite your original list — only update the adapter's filtered list:

public void filter(String search) {
    ArrayList<Devices> filteredList = new ArrayList<>();
    // Iterate over the ORIGINAL list, not the filtered one
    for (Devices item : originalDeviceList) {
        if (item.getDevicename().toLowerCase().contains(search.toLowerCase())) {
            filteredList.add(item);
        }
    }
    DevAdapter.filterList(filteredList);
    // REMOVE THIS LINE: devicelist = filteredList;
}

Step 3: Get Original Position for Database Operations

In your click listeners, find the clicked item's position in the original list instead of using the filtered list's position. First, add a way to access the adapter's filtered list (add this method to your DevAdapter):

// In DevAdapter
public ArrayList<Devices> getFilteredList() {
    return devlist;
}

Then update your click logic:

DevAdapter.setOnItemClickListener(new ListAdapter.OnItemClickListener() {
    @Override
    public void onReturnClick(int position) {
        Devices clickedDevice = DevAdapter.getFilteredList().get(position);
        // Find the original position in the full dataset
        int originalPosition = originalDeviceList.indexOf(clickedDevice);
        String childpos = String.valueOf(originalPosition); // Use original position for DB
        
        String renter = clickedDevice.getRenter();
        if( name.equals(renter)) {
            Toast.makeText(RentActivity.this,"Device RETURNED",Toast.LENGTH_SHORT).show();
            devicedb.child(childpos).child("codereturn").setValue("-");
            devicedb.child(childpos).child("statusdb").setValue("0");
            devicedb.child(childpos).child("statuscard").setValue("Available");
            devicedb.child(childpos).child("renter").setValue("-");
            
            // Update both the filtered item and original item
            clickedDevice.changeOnReturn("-","Available");
            originalDeviceList.get(originalPosition).changeOnReturn("-","Available");
            DevAdapter.notifyItemChanged(position);
        } else {
            Toast.makeText(RentActivity.this,"Not Eligible for Returning",Toast.LENGTH_SHORT).show();
        }
    }

    // Repeat the same logic for onRentClick...
    @Override
    public void onRentClick(int position) {
        Devices clickedDevice = DevAdapter.getFilteredList().get(position);
        int originalPosition = originalDeviceList.indexOf(clickedDevice);
        String childpos = String.valueOf(originalPosition);
        
        String checkstats = clickedDevice.getStatuscard();
        if(checkconnection(RentActivity.this)) {
            if (checkstats.equals("Available")) {
                devicedb.child(childpos).child("codereturn").setValue("-");
                devicedb.child(childpos).child("statusdb").setValue("1");
                devicedb.child(childpos).child("statuscard").setValue("Rented");
                devicedb.child(childpos).child("renter").setValue(name);
                
                Toast.makeText(RentActivity.this,"Device Rent Success",Toast.LENGTH_SHORT).show();
                clickedDevice.changeOnRent(name,"Rented");
                originalDeviceList.get(originalPosition).changeOnRent(name,"Rented");
                DevAdapter.notifyItemChanged(position);
            } else {
                Toast.makeText(RentActivity.this, "Device not Available to Rent", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(RentActivity.this, "NO INTERNET ACCESS", Toast.LENGTH_SHORT).show();
        }
    }
});

Solution 2: Add Original Index Field to Devices Class (More Reliable)

If indexOf doesn't work (e.g., if your Devices objects are recreated from DB queries), add an explicit original index field to your model class:

public class Devices {
    // Your existing fields...
    private int originalIndex;

    // Add setter and getter
    public void setOriginalIndex(int index) {
        this.originalIndex = index;
    }

    public int getOriginalIndex() {
        return originalIndex;
    }

    // Your other methods (changeOnReturn, changeOnRent, etc.)
}

When initializing your original list, set the index for each item:

for (int i = 0; i < originalDeviceList.size(); i++) {
    originalDeviceList.get(i).setOriginalIndex(i);
}

Then in click listeners, just use this field directly:

String childpos = String.valueOf(clickedDevice.getOriginalIndex());

Critical Notes

  • Always keep your original full dataset separate from filtered lists to avoid position confusion.
  • If using indexOf, override equals() and hashCode() in your Devices class (using a unique identifier like device ID) to ensure accurate position lookup:
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Devices devices = (Devices) o;
    return Objects.equals(getDeviceId(), devices.getDeviceId()); // Use your unique ID field
}

@Override
public int hashCode() {
    return Objects.hash(getDeviceId());
}

内容的提问来源于stack exchange,提问作者Theda Yuwana Saputra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:05:08