可过滤StickyListHeadersAdapter,notifyDataSetChanged不工作

问题描述:

我一直坚持了几个小时,这个想法是有一个可编辑列表帮助EditText。为此,我使用可过滤StickyListHeadersAdapter的StickyListHeadersListView。这里是我当前的代码:可过滤StickyListHeadersAdapter,notifyDataSetChanged不工作

public class PersonaFilterAdapter extends BaseAdapter implements StickyListHeadersAdapter, Filterable { 

private int mResource; 
private List<User> mUserList = new ArrayList<>(); 
private Set<User> mUserHashSet; 

/** Filter parameters **/ 
private ArrayList<User> mFilteredObjects = new ArrayList<>(); 
private Filter mFilter; 

public PersonaFilterAdapter(int resource, List<User> objects, Set<User> userHashSet) { 
    this.mResource = resource; 
    this.mUserList.addAll(objects); 
    this.mFilteredObjects.addAll(objects); 
    this.mUserHashSet = userHashSet; 
} 

public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 

    if (convertView == null) { 
     convertView = LayoutInflater.from(parent.getContext()).inflate(mResource, parent, false); 
     holder = new ViewHolder(); 
     holder.avatar = (SimpleDraweeView) convertView.findViewById(R.id.userAvatar); 
     holder.name = (TextView) convertView.findViewById(R.id.userName); 
     holder.position = (TextView) convertView.findViewById(R.id.userPosition); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    User user = getItem(position); 

    int size = 100; 
    String imgString = SlingCloudinary.getInstance().getAvatar(user, size, size); 
    Uri uri = Uri.parse(imgString); 
    holder.avatar.setImageURI(uri); 
    holder.name.setText(String.format("%s %s", user.getName(), user.getLastname())); 
    holder.position.setText(user.getDescription()); 

    if (mUserHashSet != null) { 
     ListView listView = (ListView) parent; 
     if (mUserHashSet.contains(user)) { 
      listView.setItemChecked(position, true); 
     } else { 
      listView.setItemChecked(position, false); 
     } 
    } 
    return convertView; 
} 

public void updateUsersList(List<User> userList) { 
    mUserList.clear(); 
    mUserList.addAll(userList); 
    mFilteredObjects.clear(); 
    mFilteredObjects.addAll(mUserList); 
    this.notifyDataSetChanged(); 
} 

public void notifyFilterDataSetChanged(List<User> userList) { 
    mFilteredObjects.clear(); 
    mFilteredObjects.addAll(userList); 
    notifyDataSetChanged(); 
} 

@Override 
public long getItemId(int position) { 
    return position; 
} 

@Override 
public User getItem(int position) { 
    return mFilteredObjects.get(position); 
} 

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

@Override 
public Filter getFilter() { 
    if (mFilter == null) { 
     mFilter = new AppFilter(); 
    } 
    return mFilter; 
} 

class ViewHolder { 
    SimpleDraweeView avatar; 
    TextView name; 
    TextView position; 
} 

class HeaderViewHolder { 
    TextView text; 
} 

@Override 
public View getHeaderView(int position, View convertView, ViewGroup parent) { 
    HeaderViewHolder holder; 

    if (convertView == null) { 
     holder = new HeaderViewHolder(); 
     convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_section_persona, parent, false); 
     holder.text = (TextView) convertView.findViewById(R.id.personaSectionText); 
     convertView.setTag(holder); 
    } else { 
     holder = (HeaderViewHolder) convertView.getTag(); 
    } 

    // set header text as first char in name 
    CharSequence headerChar = getItem(position).getName().subSequence(0, 1); 
    holder.text.setText(headerChar); 

    return convertView; 
} 

@Override 
public long getHeaderId(int position) { 
    return getItem(position).getName().subSequence(0,1).charAt(0); 
} 

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

private class AppFilter extends Filter { 

    @Override 
    protected FilterResults performFiltering(CharSequence chars) { 
     FilterResults result = new FilterResults(); 
     if (chars != null && chars.length() > 0) { 
      String mask = chars.toString(); 
      ArrayList<User> userList = new ArrayList<>(); 

      for (User user : mUserList) { 
       if (keepObject(user, mask)) { 
        userList.add(user); 
       } 
      } 
      result.count = userList.size(); 
      result.values = userList; 
     } else { 
      // add all objects 
      result.values = mUserList; 
      result.count = mUserList.size(); 
     } 
     return result; 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    protected void publishResults(CharSequence constraint, FilterResults results) { 
     if (results.count > 0) { 
      notifyFilterDataSetChanged((List<User>) results.values); 
     } else { 
      notifyDataSetInvalidated(); 
     } 
    } 
} 

private boolean keepObject(User user, String mask) { 
    mask = mask.toLowerCase(); 
    return user.getName().toLowerCase().startsWith(mask); 
} 
} 

现在一切都在第一次显示好,我叫这就要求notifyDataSetChanged和正常工作的updateUsersList列表功能,我可以看到所有章节的列表。

之后使用的EditText时,通过键入字母例如在筛选类返回我2个过滤项目,我再通的2项的这个名单notifyFilterDataSetChanged功能,使粘列表仅显示2项。在这一点上它失败了,整个列表仍然是一样的。我可能在这一点上失踪,我一直在阅读所有好的建议,但徒劳无功。任何想法?

首先,你有一个错误的getItemId实现。如果你使用hasStableIds(true),你不应该依赖位置。尝试使它像

@Override 
public long getItemId(int position) { 
    return getItem(position).getId(); 
} 

我想你在你的用户类中有某种类型的ID,不是吗?

其次,你是否在UI线程中调用publishResults?尝试使runOnUiThread()或listView.post()检查一切是否正确。

三,你有几个适配器初始化?检查是否将事件传递给正确的事件(绑定到列表视图的事件)。

+0

这是你提到的一个好点,我用这个hasStableIds而不知道它做了什么。即使设置为false,这仍然不起作用。我也尝试runOnUIThread和listView.post(),仍然不幸运.. –

+0

除了你的实现似乎对我来说很正常。让我澄清一下 - 即使您的过滤的实现返回正确的结果(提供正确大小的过滤列表等)并通过notifyFilterDataSetChanged通知适配器,该列表仅显示初始值(未过滤的列表)?可能你有几个适配器初始化并将事件传递给错误的?你可以在传递OnTextChanged事件之前和之后检查适配器大小,但直接像listView.getAdapter()。getCount()那样检查它吗? – aelimill

+0

并返回hasStableIds为true,只是实现正常的逻辑getItemId() – aelimill