我有一个在一组图像中搜索的活动。图像显示在画廊中。有一个 EditText,用户可以在其中输入搜索词。当用户在 EditText 中输入文本时,画廊会根据输入的文本进行过滤。
我做了一个SearchResultAdapter extends BaseAdapter implements Filterable
基本上可以正常工作的。如果用户输入文本,适配器中的数据将被过滤。我记录了结果:到目前为止它有效。然后我调用 notifyAdapterSetChanged 以便图库显示更新的数据集。notifyAdapterSetChanged 实际被调用,并且请求被画廊接收,因为它调用我的适配器 getCount() (我记录了所有调用)。
将选择设置为 0 由于 IndexOutOfBoundsException 导致应用程序崩溃,正如我在画廊没有项目时所期望的那样。画廊仍然显示之前在其中的所有图像。
问题是:当数据集为空(即用户输入的搜索词不适合任何图像)时,图库不会显示更新。图库接收 notifyAdapterSetChanged,查询适配器的项目计数(为 0)并更新滚动限制。它不会更新图库中显示的图像。我不能再滚动图像了,因为基本上没有图像可以显示,但图像并没有从图库中删除。在用户看来,就好像画廊冻结了一样。
当无效的搜索词被删除(即数据集不为空)时,图库会显示正确的图像。同样在某些情况下,画廊会显示空列表,例如当应用程序最小化然后重新打开时。我无法重现画廊清空自身的条件(除了最小化/重新打开应用程序):
我尝试过使画廊无效和 requestLayout(),但它没有帮助。有谁知道如何让画廊更新显示的图像列表?
这里是当用户输入与图像不匹配的文本时的日志消息:
[SearchResultAdapter.SearchFilter] Results: 0
[SearchResultAdapter.SearchFilter] called notifyDataSetChanged()
[SearchResultAdapter.getCount()] getCount called: dateset size 0
[SearchResultAdapter.getCount()] getCount called: dateset size 0
请注意,适配器实际上是如何由库在数据集大小上调用的
活动中的初始化代码:
final Gallery gallery = (Gallery) findViewById(R.id.search_results);
final SearchResultAdapter adapter = new SearchResultAdapter(this, gallery);
gallery.setAdapter(adapter);
EditText searchField = (EditText) findViewById(R.id.search_searchfield);
searchField.addTextChangedListener(new TextWatcher()
{
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{
// TODO unhardcode criterion
adapter.putFilterTerm(SearchCriteria.OFFERING, s.toString());
adapter.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{
// do nothing
}
@Override
public void afterTextChanged(Editable s)
{
// do nothing
}
});
和 SearchResultAdapter(无关紧要的行被省略):
public class SearchResultAdapter extends BaseAdapter implements Filterable
{
private Context context;
private Filter filter;
public void putFilterTerm(SearchCriteria key, String value)
{
filterTerms.put(key, value);
}
public boolean containsFilterTerm(SearchCriteria key)
{
return filterTerms.containsKey(key);
}
public String getFilterTerm(SearchCriteria key)
{
return filterTerms.get(key);
}
List<PageContainer> completeList = new ArrayList<PageContainer>();
List<PageContainer> currentList = new ArrayList<PageContainer>();
Map<SearchCriteria, String> filterTerms = new HashMap<SearchCriteria, String>();
View view;
public SearchResultAdapter(Context context, View gallery)
{
this.context = context;
this.view = gallery;
for (ContentPropertyContainer page : Model.getInstance()
.getRootContainer().getChildren())
{
completeList.add((PageContainer) page);
}
currentList.addAll(completeList);
}
@Override
public int getCount()
{
return currentList.size();
}
@Override
public Object getItem(int position)
{
return currentList.get(position);
}
@Override
public long getItemId(int position)
{
PageContainer item = currentList.get(position);
for (int i = 0; i < completeList.size(); ++i)
{
if (completeList.get(i) == item)
{
return i;
}
}
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View listview = convertView;
// Code left out here tries to reuse the convertView
// like Romain Guy said in a Google I/O Talk
return listview;
}
private class ResultList
{
ResultList(List<PageContainer> results)
{
this.results = results;
}
List<PageContainer> results;
}
@Override
public Filter getFilter()
{
// implements Filterable
if (filter == null)
{
filter = new SearchFilter();
}
return filter;
}
private class SearchFilter extends Filter
{
SearchFilter()
{
// do nothing, needed for visibility
}
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults results = new FilterResults();
// Code left out here filters the list
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results)
{
if (results == null)
{
return;
}
if (results.values instanceof ResultList)
{
currentList = ((ResultList) (results.values)).results;
notifyDataSetChanged();
}
}
}
}
编辑:将画廊的可见性设置为不可见,然后再次可见解决了这个问题。
view.post(new Runnable()
{
@Override
public void run()
{
view.setVisibility(View.INVISIBLE);
view.setVisibility(View.VISIBLE);
}
});
有更好的解决方案吗?这对我来说似乎相当骇人听闻。