notifyDataSetChanged无效

8
我的应用程序使用了一个MultiColumnListView(https://github.com/huewu/PinterestLikeAdapterView)库,正如其名称所示,它可以帮助创建多列列表视图。
这个库非常好,但是正如他们指出的那样,不支持过滤筛选。
因此,我正在尝试使用简单的编辑文本创建自己的文本过滤功能。
最终,我成功地过滤了列表,但现在我需要刷新listView并重新调用setAdapter,因为我将列表传递给它。
MyAdapter adapter = new MyAdapter(this,myList);
listView.setAdapter(adapter);

当我执行 listView.invalidateViews() 或者 adapter.notifyDataSetChanged() 时,listView 被刷新了,但是显示的还是旧的列表。
重新调用 setAdapter 是最好的方式吗?或者还有其他方法可以实现这个功能。
提前感谢您的帮助。 编辑:
//Method that filters the list
Log.i("On filter myList.size()",""+myList.size());      
adapter.notifyDataSetChanged();

//on the Adapter
Log.i("On Adapter myList.size()",""+myList.size());

日志:

enter image description here

适配器类:

public class MiAdaptadorListaComercios extends BaseAdapter{

//Textview and Imageviews declarations

private Context contexto;

private List<Comercio> myList;

public MiAdaptadorListaComercios(Context c,List<Comercio> myList){
    this.contexto = c;
    this.myList = new ArrayList<Comercio>();
    this.myList = myList;
}
@Override
public int getCount() {
    Log.i("On Adapter myList.size()",""+listaComercios.size());
    return myList.size();
}

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

@Override
public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) 
{
    View view =null;

    if(convertView == null)
    {
        LayoutInflater inflater = (LayoutInflater) contexto.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.list_cell, null);
    }
    else{
        view = convertView;
    }

    //set views Texteviews text,font etc...

    return view;
}

}

活动类:

public class ListaComercio extends Activity {

    private MultiColumnListView mAdapterView = null;
    EditText searchBar;
    private ArrayList<Comercio> myList;
    private ArrayList<Comercio> filteredList;
    MyAdapter adapter;


    public ListaComercio(){
        myList = new ArrayList<Comercio>();
        filteredList = new ArrayList<Comercio>();       
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.lista_comercios);

        mAdapterView = (MultiColumnListView) findViewById(R.id.list);

        adapter = new MyAdapter(ListaComercio.this,myList);

        mAdapterView.setAdapter(adapter);


        searchBar.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    CharSequence filer =  v.getText();

                    for(Comercio co : myList)
                    {
                        if(co.getName().contains(filer))
                        {
                            filteredList.add(co);
                        }
                    }

                    myList = filteredList;

                    Log.i("On filter myList.size()",""+myList.size());  

                    myList.clear();
                    adapter.notifyDataSetChanged();
                    //mAdapterView.invalidateViews();

                    return true;
                }
                return false;
            }
        });
    }
    }

请在下面发布您设置此适配器的活动代码。 - M D
谢谢,我刚刚添加了它 @MD - Andoxko
这里是解释 https://dev59.com/-mQo5IYBdhLWcg3wUNzY#20479071 - Sazzad Hissain Khan
2个回答

21

只需更改您的myList并调用adapter.notifyDataSetChanged(),不要每次设置新适配器。

在自定义适配器的构造函数中,请调用以ArrayList为参数的super

调用此方法:

public MiAdaptadorListaComercios(Context c,List<Comercio> myList){
    super(c,0,myList);
    this.contexto = c;
    this.myList = myList;
}

你可以保留适配器,问题在于这一行:

myList = filteredList;

你应该改变列表本身而不是更改引用。

myList.clear();
myList.addAll(filteredList);

通过这样做,您将丢失原始列表,因此我建议保留另一个名为originalList的列表,该列表将具有完整的列表,并通过以下方式在onCreate中初始化myList:

myList=new ArrayList(originalList);

所以每次想要重新设置时,只需调用:

myList.clear();
myList.addAll(originalList);    

而且在

    for(Comercio co : originalList)
            {
                if(co.getName().contains(filer))
                {
                    filteredList.add(co);
                }
            }

谢谢您的快速回答,但我正在做的就是这个,但它并没有起作用。我已经编辑了我的问题以澄清。 - Andoxko
请分享你的MyAdapter类。 - vipul mittal
再次感谢。但是当我在构造函数中调用super()时,没有任何改变;如果我尝试调用super(myList),则会出现错误,告诉我必须删除参数以匹配BaseAdapter。我做错了什么? - Andoxko
谢谢,但不幸的是我在Eclipse上遇到了这个错误[errorImage1](http://postimg.org/image/6fvh0isct/)[errorImage2](http://postimg.org/image/9ji3yw3mv/)。尽管我已经编辑了问题并添加了设置适配器和列表的“Activity”,但也许错误就在那里。再次感谢您。 - Andoxko
使用ArrayAdapter进行扩展。 - vipul mittal
成功了!问题出在列表本身而不是适配器。非常感谢您!你是我的救命恩人!! :) - Andoxko

6

你需要清除旧的 myList.clear(),然后调用adapter.notifyDataSetChanged()

更新:

将你的代码更改为:

public MiAdaptadorListaComercios(Context c,List<Comercio> myList){
this.contexto = c;
this.myList = new ArrayList<Comercio>();
}

另外,像这样做。
myList.clear();
myList.addAll(originalList);   

1
谢谢您的回答,但不幸的是它并没有起作用。我已经编辑了我的问题并且加入了更多细节。希望这能帮助您猜测我做错了什么。 - Andoxko
但是当我这样做时,列表总是为空...或者我应该在new之后添加this.myList = myList吗? - Andoxko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接