android自定义列表视图适配器不会更新getView中的视图数

时间:2012-01-07 16:30:14

标签: android listview filter dataset adapter

我有一个带有自定义适配器的listView。 我的活动中有一个编辑文本视图,用户可以在其中键入以过滤列表视图中的内容。

让我们说列表视图中有两个项目。执行过滤后,ArrayList减少为一个元素。 问题是仍然为前两行执行了getView方法。

这是我的代码。

ListActivity:

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 =&gt; get(postion)失败。

希望现在明白。

2 个答案:

答案 0 :(得分:2)

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

@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();
    }

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

答案 1 :(得分:0)

我认为你不需要

  

teams =(ArrayList)results.values;

在publishResults函数中。