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); } }
核心优化点说明
- 包装类绑定数据:把标签本身和接口返回的状态、描述绑定,让过滤逻辑能直接拿到
status值 - 避免重复请求:把网络请求从
getView移到标签添加时,大幅减少不必要的网络请求 - 状态匹配逻辑:过滤时直接对比
tagInfo.getStatus(),还做了大小写兼容,避免选项和接口返回值大小写不一致导致的匹配失败
内容的提问来源于stack exchange,提问作者MSQMooney
相关产品推荐
相关产品推荐

