1

我的代码有问题,我对适配器内的 HashMap 执行搜索。它工作正常,但是当我快速删除 EditText 中的所有字母时,适配器会显示输入的第一个完整字符串的列表,而不是所有元素的列表。

示例:我键入 James,视图将获取地图中的所有 James,但如果我快速删除 EditText(按返回),则该方法会立即执行搜索并显示任何子字符串的正确列表(jame、jam、ja、 j)但最后他再次显示继承“詹姆斯”的列表而不是完整的联系人列表

感谢您的任何回答!

public class ContactsActivity extends ListActivity {

private HashMap<String, UserEntry> all_map_jid=new HashMap<String, UserEntry>();
private ArrayList<String> all_mkey=new ArrayList<String>();



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_contacts);
    getListView().setTextFilterEnabled(true);


    final EditText searchText = (EditText) findViewById(R.id.searchbox);


    TextWatcher textWatcher = new TextWatcher() {

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

            //... your logic
             adapter.getFilter().filter(s.toString());

        }
        @Override
        public void afterTextChanged(Editable arg0) {
            // ... your logic

        }
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            // ... your logic
        }
    };

    searchText.addTextChangedListener(textWatcher);}


public class RosterAdapter extends BaseAdapter implements Filterable{

    //private ViewHolder holder;
    private LayoutInflater inflater;


    private HashMap<String, UserEntry> mappa_users=null;
    private ArrayList<String> mKeys;

    public RosterAdapter(){
        this.mappa_users =new HashMap<String, UserEntry>();
        this.inflater=          (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.mKeys=new ArrayList<String>();
    }
    @Override
    public int getCount() {
        return mappa_users.size();
    }

    @Override
    public UserEntry getItem(int position) {
        return mappa_users.get(mKeys.get(position));
    }

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


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



        ViewHolder holder;


        if (convertView == null) {

            convertView = inflater.inflate(R.layout.layout_row, null);

            // Creates a ViewHolder and store references to the two children
            // views we want to bind data to.
            holder = new ViewHolder();
            holder.username = (TextView) convertView.findViewById(R.id.user_info);
            holder.availability = (ImageView) convertView.findViewById(R.id.user_availability);
            holder.user_ic = (ImageView) convertView.findViewById(R.id.icon);


            // Keep track of the view holder as a tag of the view
            convertView.setTag(holder);

        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag(); 
        }



        String user = getItem(position).getUserName();
        //Log.e("Nome","username "+user);
        holder.username.setText(user);



        if(!(getItem(position).getUserStatus())){

            System.out.println("unavailable");
            holder.availability.setImageResource(R.drawable.ic_not_available);  

        }else{

            holder.availability.setImageResource(R.drawable.ic_available);
        }

        //do your view stuff here

        return convertView;
    }





    @Override
    public Filter getFilter() {
        return new Filter() {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {                 
                mappa_users = (HashMap<String,UserEntry>) results.values;
                mKeys= new ArrayList<String>(Arrays.asList(mappa_users.keySet().toArray(new String[mappa_users.size()])));
                Collections.sort(mKeys, new RosterEntryComparator(mappa_users));

                notifyDataSetChanged();
                }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                HashMap<String,UserEntry> searched_user=new HashMap<String,UserEntry>();
                FilterResults results = new FilterResults();


                if (constraint!= null && constraint.toString().length() > 0) {

                SmithWaterman metric = new SmithWaterman();

               for(String element : all_mkey){
                   //La mappa dell'adapter è riempito con le sole entry simily all'occorrenza ricercata
                   if (metric.getSimilarity(constraint.toString().toLowerCase(), all_map_jid.get(element).getUserName().toLowerCase()) >= 0.8 ){

                       UserEntry rEntry=all_map_jid.get(element);

                       searched_user.put(element, rEntry );

                   }

               }

              results.values = searched_user;
              results.count = searched_user.size();

                }
                else{


                        results.values = all_map_jid;
                        results.count = all_map_jid.size();

                }

                return results;
            }
        };
    }
4

1 回答 1

3

解决了

我解决了这个问题,问题是我在任何新类型上都创建了一个新的过滤器对象,使用相同的过滤器效果很好,因为正如 android 文档中所写:

public final void 过滤器(CharSequence 约束,Filter.FilterListener 监听器)

在 API 级别 1 中添加 启动异步过滤操作。调用此方法会取消之前所有未执行的过滤请求,并发布一个稍后将执行的新过滤请求。

这是正确的代码:

//My Adapter 
public class RosterAdapter extends BaseAdapter implements Filterable{

    //private ViewHolder holder;
    private LayoutInflater inflater;

    private ItemsFilter mFilter;

    private HashMap<String, UserEntry> mappa_users=null;
    private HashMap<String, UserEntry> all_map_jid=null;
    private ArrayList<String> all_mkey=null;;
    private ArrayList<String> mKeys;


    public RosterAdapter(){
        this.mappa_users =new HashMap<String, UserEntry>();
        this.inflater= (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.all_map_jid=new HashMap<String, UserEntry>();
        this.all_mkey=new ArrayList<String>();
        this.mKeys=new ArrayList<String>();
    }
    @Override
    public int getCount() {
        return mappa_users.size();
    }

    @Override
    public UserEntry getItem(int position) {
        return mappa_users.get(mKeys.get(position));
    }

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


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



        ViewHolder holder;


        if (convertView == null) {

            convertView = inflater.inflate(R.layout.layout_row, null);

            // Creates a ViewHolder and store references to the two children
            // views we want to bind data to.
            holder = new ViewHolder();
            holder.username = (TextView) convertView.findViewById(R.id.user_info);
            holder.availability = (ImageView) convertView.findViewById(R.id.user_availability);
            holder.user_ic = (ImageView) convertView.findViewById(R.id.icon);


            // Keep track of the view holder as a tag of the view
            convertView.setTag(holder);

        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag(); 
        }



        String user = getItem(position).getUserName();
        //Log.e("Nome","username "+user);
        holder.username.setText(user);



        if(!(getItem(position).getUserStatus())){


            holder.availability.setImageResource(R.drawable.ic_not_available);  

        }else{

            holder.availability.setImageResource(R.drawable.ic_available);
        }

        //do your view stuff here

        return convertView;
    }





    /**
     * Implementing the Filterable interface.
     */
    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new ItemsFilter();
        }
        return mFilter;}


        /**
         * Custom Filter implementation for the items adapter.
         *
         */
        private class ItemsFilter extends Filter {
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                adapter.mappa_users = (HashMap<String,UserEntry>) results.values;
                adapter.mKeys= new ArrayList<String>(Arrays.asList(adapter.mappa_users.keySet().toArray(new String[adapter.mappa_users.size()])));
                Collections.sort(mKeys, new RosterEntryComparator(adapter.mappa_users));

                notifyDataSetChanged();
                Log.e("fine", "Terminato filtraggio "+constraint);

                }


            @Override
            protected  FilterResults performFiltering(CharSequence constraint) {

                HashMap<String,UserEntry> searched_user=new HashMap<String,UserEntry>();
                FilterResults results = new FilterResults();


                if (constraint!= null && constraint.toString().length() > 0) {

                SmithWaterman metric = new SmithWaterman();

               for(String element : all_mkey){
                   //La mappa dell'adapter è riempito con le sole entry simily all'occorrenza ricercata
                   if (metric.getSimilarity(constraint.toString().toLowerCase(), all_map_jid.get(element).getUserName().toLowerCase()) >= 0.8 ){

                       UserEntry rEntry=all_map_jid.get(element);

                       searched_user.put(element, rEntry );

                   }

               }

              results.values = searched_user;
              results.count = searched_user.size();

                }
                else{


                        results.values = all_map_jid;
                        results.count = all_map_jid.size();

                }

                return results;
            }
        };
于 2012-12-13T11:50:55.610 回答