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

Android:求助按RFID标签状态用Spinner过滤ListView

解决ListView按Tag Status过滤的问题

你现在的核心问题很明确:当前过滤逻辑只检查标签的tagTitle,但你需要根据从JSON接口获取的status来过滤,而且没有把异步获取的status和对应的UgiTag绑定起来,另外还有个隐藏坑:你在getView里每次绘制视图都会发起网络请求,这会导致大量重复请求,性能拉胯。

下面是完整的分步解决方案:


第一步:创建包装类绑定标签的完整信息

UgiTag本身不包含从JSON接口获取的status、description这些字段,我们需要一个包装类把这些数据和标签本身绑定:

public class TagWithInfo {
    private UgiTag ugiTag;
    private String tagTitle;
    private String status;
    private String description;
    private boolean shouldDisplay; // 记录是否需要显示该标签

    public TagWithInfo(UgiTag ugiTag) {
        this.ugiTag = ugiTag;
        this.tagTitle = ugiTag.toString().substring(14);
    }

    // Getter & Setter 方法
    public UgiTag getUgiTag() { return ugiTag; }
    public String getTagTitle() { return tagTitle; }
    public String getStatus() { return status; }
    public void setStatus(String status) { this.status = status; }
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    public boolean isShouldDisplay() { return shouldDisplay; }
    public void setShouldDisplay(boolean shouldDisplay) { this.shouldDisplay = shouldDisplay; }
}

第二步:修改Activity的数据源类型

把原来的List<UgiTag>改成List<TagWithInfo>,让列表存储包含状态信息的完整标签对象:

// 在rfid_status类中修改
public List<TagWithInfo> tagArray = new ArrayList<>();
// ...
epcAdapter = new EPCAdapter(this);

第三步:重构Adapter,优化请求逻辑+修改过滤规则

原来的getView重复请求的问题必须解决,同时把过滤逻辑从tagTitle切换到status:

public class EPCAdapter extends BaseAdapter implements Filterable {
    private rfid_status rfidStatus;
    private List<TagWithInfo> originalTags;
    private List<TagWithInfo> filteredTags;

    EPCAdapter(rfid_status rfidStatus) {
        super();
        this.rfidStatus = rfidStatus;
        this.filteredTags = rfidStatus.tagArray;
    }

    class TagHolder {
        TextView tagNumber, tagDetails, tagStatus;
    }

    @Override
    public boolean hasStableIds() { return true; }

    @Override
    public int getCount() { return filteredTags.size(); }

    @Override
    public Object getItem(int position) { return filteredTags.get(position); }

    @Override
    public long getItemId(int position) { 
        return filteredTags.get(position).getUgiTag().getEpc().hashCode(); 
    }

    @SuppressLint("InflateParams")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final TagHolder tagHolder;
        final TagWithInfo tagInfo = filteredTags.get(position);

        if (convertView == null) {
            convertView = LayoutInflater.from(rfid_status.this)
                    .inflate(R.layout.tag_row, null);
            tagHolder = new TagHolder();
            tagHolder.tagNumber = convertView.findViewById(R.id.tagHere);
            tagHolder.tagStatus = convertView.findViewById(R.id.statHere);
            tagHolder.tagDetails = convertView.findViewById(R.id.descHere);
            convertView.setTag(tagHolder);
        } else {
            tagHolder = (TagHolder) convertView.getTag();
        }

        // 直接从包装类取数据,无需重复请求
        tagHolder.tagNumber.setText(tagInfo.getTagTitle());
        if (tagInfo.getStatus() != null) {
            tagHolder.tagStatus.setText(tagInfo.getStatus());
        }
        if (tagInfo.getDescription() != null) {
            tagHolder.tagDetails.setText(tagInfo.getDescription());
        }

        return convertView;
    }

    // 新增:统一获取标签信息的方法,避免重复请求
    public void fetchTagData(final TagWithInfo tagInfo) {
        Uri.Builder jsonBuild = new Uri.Builder();
        jsonBuild.scheme("http")
                .authority("thirdstreamv2")
                .appendPath("utilities")
                .appendPath("HandheldGreenScreen")
                .appendQueryParameter("assetid", tagInfo.getTagTitle());
        String jsonURL = jsonBuild.build().toString();

        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, jsonURL, null,
                response -> {
                    try {
                        boolean display = response.getString("display").equals("true");
                        tagInfo.setShouldDisplay(display);
                        if (display) {
                            tagInfo.setStatus(response.getString("status"));
                            tagInfo.setDescription(response.getString("description"));
                        } else {
                            rfidStatus.tagArray.remove(tagInfo);
                        }
                        notifyDataSetChanged();
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }, error -> error.printStackTrace());
        
        rfidStatus.rQ.add(request);
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                filteredTags = (List<TagWithInfo>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                List<TagWithInfo> tempFiltered = new ArrayList<>();
                String filterText = constraint.toString().trim();

                if (originalTags == null) {
                    originalTags = new ArrayList<>(rfidStatus.tagArray);
                }

                if (filterText.isEmpty()) {
                    // 空条件显示所有有效标签
                    tempFiltered.addAll(originalTags);
                } else {
                    // 根据status过滤,忽略大小写兼容选项差异
                    for (TagWithInfo tagInfo : originalTags) {
                        String tagStatus = tagInfo.getStatus();
                        if (tagStatus != null && tagStatus.equalsIgnoreCase(filterText)) {
                            tempFiltered.add(tagInfo);
                        }
                    }
                }

                results.count = tempFiltered.size();
                results.values = tempFiltered;
                return results;
            }
        };
    }
}

第四步:调整标签扫描后的处理逻辑

在扫描到新标签的回调里,创建TagWithInfo对象并调用Adapter的方法获取数据,避免重复添加:

@Override
public void inventoryTagFound(UgiInventoryReader reader, UgiTag ugiTag) {
    // 检查标签是否已存在
    boolean isDuplicate = false;
    for (TagWithInfo tagInfo : tagArray) {
        if (tagInfo.getUgiTag().getEpc().equals(ugiTag.getEpc())) {
            isDuplicate = true;
            break;
        }
    }
    if (!isDuplicate) {
        TagWithInfo newTag = new TagWithInfo(ugiTag);
        tagArray.add(newTag);
        epcAdapter.fetchTagData(newTag);
    }
}

核心优化点说明

  1. 包装类绑定数据:把标签本身和接口返回的状态、描述绑定,让过滤逻辑能直接拿到status值
  2. 避免重复请求:把网络请求从getView移到标签添加时,大幅减少不必要的网络请求
  3. 状态匹配逻辑:过滤时直接对比tagInfo.getStatus(),还做了大小写兼容,避免选项和接口返回值大小写不一致导致的匹配失败

内容的提问来源于stack exchange,提问作者MSQMooney

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:38:45