android自定义 ListView 适配器不更新getView中的 View 数

标签 android listview filter dataset adapter

我有一个带有自定义适配器的 ListView 。 我的 Activity 中有一个编辑 TextView ,用户可以在其中键入以过滤 ListView 中的内容。

假设我在 ListView 中有两个项目。过滤后,ArrayList 减少为一个元素。 问题是 getView 方法仍然为前两行执行。

这是我的代码。

列表 Activity :

public class TeamsListActivity extends ListActivity {

    private ArrayList<Team> teams = new ArrayList<Team>();
    private TeamsListAdapter teamsListAdapter = null;
    private EditText searchInput = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.teams_list);

        // get association id from the intent.
        int afId = getIntent().getExtras().getInt("afId");
        Log.i(MainActivity.TAG, "id_association =" + afId);

        // get the teams from the association.
        this.teams = TeamsDAO.getInstance(getApplicationContext())
                .getTeamsByAssociation(afId);


        // inits the list adapter
        teamsListAdapter = new TeamsListAdapter(this, teams);

        setListAdapter(teamsListAdapter);

        // gets the search input view
        searchInput = (EditText) findViewById(R.id.teams_list_search_box);
        searchInput.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {

            }

            public void afterTextChanged(Editable s) {
                Log.d(Constants.TAG,"Teams search: " + s.toString());
                teamsListAdapter.getFilter().filter(s);             
            }
        });

    }


}

我的适配器

public class TeamsListAdapter extends ArrayAdapter<Team> implements Filterable {

    private ArrayList<Team> teams = null;
    private Context context = null;

    public TeamsListAdapter(Context context,
            ArrayList<Team> objects) {

        super(context, R.layout.teams_list_row, objects);

        this.context = context;
        this.teams = objects;

    }

    @Override
    public View getView(int position, View v, ViewGroup parent) {

        if (v == null) {
            LayoutInflater vi = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.teams_list_row, null);
        }

            Team t = teams.get(position);
            if (t != null) {

                TextView txtTeamName = (TextView) v.findViewById(R.id.teams_list_team_name);

                txtTeamName.setText(t.getName());

                ImageView ivTeamLogo = (ImageView) v.findViewById(R.id.teams_list_team_logo);
                ivTeamLogo.setImageResource(R.drawable.af_braga);
            }



        return v;
    }


    @Override
    public Filter getFilter() {
        return new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                  Log.d(Constants.TAG, "**** Search RESULTS for: " + constraint);
                   teams = (ArrayList<Team>) results.values;
                   Log.d(Constants.TAG,"size:"+teams.size());
                   TeamsListAdapter.this.notifyDataSetChanged();

            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                Log.d(Constants.TAG, "**** PERFORM TEAK FILTERING for: " + constraint);
                ArrayList<Team> filteredResults = getFilteredResults(constraint);

                FilterResults results = new FilterResults();
                results.values = filteredResults;

                return results;
            }

            /**
             * filters the teamsList 
             * @param constraint String The text to search
             * @return ArrayList<Team>
             */
            private ArrayList<Team> getFilteredResults(CharSequence constraint) {
                ArrayList<Team> teams = TeamsListAdapter.this.teams;
                ArrayList<Team> filteredTeams = new ArrayList<Team>();
                for(int i=0;i< teams.size();i++){
                    if(teams.get(i).getName().toLowerCase().startsWith(constraint.toString().toLowerCase())){
                        filteredTeams.add(teams.get(i));
                    }
                }

                return filteredTeams;
            }
        };

    }
}

问题的澄清。

1.假设我的列表开始显示两个元素。 2. 用户在编辑文本中插入一些文本来过滤列表内容,这导致更新后的 arrayList 只有一个与查询匹配的元素。 3. 在调用 notifyDataSetChanged 之后,getView 仍然被调用,就像在执行 Team t = teams.get(position) 时数据集中有两行导致 IndexOutOfBoundsException 因为 arrayList 现在只有一个元素所以当 position = 1 => get (职位)失败。

希望现在晴朗。

最佳答案

好吧,我解决了我的问题。 我需要像这样覆盖我的适配器中的几个方法。

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


    @Override
    public Team getItem(int position) {
        return teams.get(position);
    }


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

现在我发现我的搜索实现存在问题。因为我正在更新原始数据集,所以搜索只能进行一次。如果我尝试返回到原始列表,我不能,因为我的原始数据数组已被修改。使用数据库查询很容易解决,而不是过滤数组列表。

关于android自定义 ListView 适配器不更新getView中的 View 数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8771173/

相关文章:

javascript - 从表中删除行(删除的行数多于选定的行数)

android - cordova 模拟 android 在 CMD 中永远卡在加载中

python - 如何在字典列表中添加新的 key 对而不修改实际的字典列表?

android如何设置以编程方式准备的arrayAdapter布局

listview - 删除 ListView Row Titanium

c# - 在 WPF ListView C# 中获取第一个可见项

android - PopupMenu 图标不显示

sql - 如何在 Spark DataFrame 上应用自定义过滤功能

android - 我想在运行时在屏幕上显示多个标记,这些标记具有从服务器接收到的不同 ID

java - 如何在android中持久化一个对象?