ListView, использующий пользовательский адаптер для реализации фильтра, получает исключение IndexOutOfBoundsException

У меня есть пользовательский ListView. Он работает нормально, за исключением случаев, когда вы пытаетесь отфильтровать поиск пользователя.

Код для отображения ListView:

private void listShow() {
    warranties=db.getAllServWarr();
    adapter=new WarrantyAdapter(serviceswarranty_activity.this,warranties);
    listView.setAdapter(adapter);
}

Код, реализующий фильтр в пользовательском адаптере:

public class WarrantyAdapter extends ArrayAdapter implements Filterable{
private ArrayList<ServicesWarranty> warrantyList;
private ArrayList<ServicesWarranty> filteredList;

private ItemFilter mFilter = new ItemFilter();
private Context context;
private int currPosition;
public WarrantyAdapter(@NonNull Context context,ArrayList<ServicesWarranty> warrantyList) {
    super(context, R.layout.serviceswarranty_item,warrantyList);
    this.warrantyList=warrantyList;
    this.filteredList=warrantyList;
    this.context=context;
}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    ServicesWarranty sw=warrantyList.get(position);
    currPosition=position;
    WarrantyAdapter.ViewHolder holder;
    if(convertView==null){
        LayoutInflater inflater=(LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView=inflater.inflate(R.layout.serviceswarranty_item,parent,false);
        holder=new WarrantyAdapter.ViewHolder();
        holder.lockno=(TextView)convertView.findViewById(R.id.lockNum_warrantyitem);
        holder.fromdate=(TextView)convertView.findViewById(R.id.fromDate_warrantyItem);
        holder.todate=(TextView)convertView.findViewById(R.id.toDate_warrantyItem);
        holder.editIc=(ImageView)convertView.findViewById(R.id.editic_warrantyItem);
        holder.deleteIc=(ImageView)convertView.findViewById(R.id.deleteic_warrantyItem);
        convertView.setTag(holder);
    }else{
        holder=(WarrantyAdapter.ViewHolder) convertView.getTag();
    }
    holder.fill(sw);
    return convertView;
}
private class ViewHolder{
    public TextView lockno;
    public TextView fromdate;
    public TextView todate;
    public ImageView editIc;
    public ImageView deleteIc;
    public void fill(final ServicesWarranty sw){
        lockno.setText(String.valueOf(sw.getLockNumber()));
        fromdate.setText(sw.getBeginDate());
        todate.setText(sw.getEndDate());
        editIc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(context,Add2warranty.class);
                intent.putExtra("AddedWarrantyLockNo",sw.getLockNumber().toString());
                context.startActivity(intent);
            }
        });
        deleteIc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder deleteAlert=new AlertDialog.Builder(context);
                deleteAlert.setMessage("آیا از حذف گارانتی با شماره قفل "+sw.getLockNumber().toString()+" اطمینان دارید؟")
                        .setPositiveButton("بله", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                AppDBHelper db=new AppDBHelper(context);
                                boolean res=db.deleteFromWarranty(sw.getID());
                                if(res) {
                                    Toast.makeText(context, "Delete successfully", Toast.LENGTH_SHORT).show();
                                    warrantyList.remove(currPosition);
                                    notifyDataSetChanged();
                                }

                            }
                        })
                        .setNegativeButton("خیر",null)
                        .show();
            }
        });
    }
}
public Filter getFilter() {
    return mFilter;
}

private class ItemFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        String filterString = constraint.toString();

        FilterResults results = new FilterResults();

        final List<ServicesWarranty> list = filteredList;

        int count = list.size();
        final ArrayList<ServicesWarranty> nlist = new ArrayList<ServicesWarranty>(count);

        String filterableString ;

        for (int i = 0; i < count; i++) {
            filterableString = list.get(i).getLockNumber().toString();
            if (filterableString.toLowerCase().contains(filterString)) {
                nlist.add(list.get(i));
            }
        }

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

        return results;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        warrantyList = (ArrayList<ServicesWarranty>) results.values;
        notifyDataSetChanged();
    }
}
}

а также я добавляю это в свою деятельность, чтобы включить поиск по фильтру

inputSearch.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String s) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String s) {
            if(s.length()>0)
                adapter.getFilter().filter(s);
            return false;
        }
    });

Когда я отлаживаю эту программу, adapter.getFilter().filter(s); работает правильно, но ближе к концу функции программа принудительно закрывается.

Вот моя информация о логарифме

FATAL EXCEPTION: main                                                                  
Process: com.example.zahra.prj1, PID: 18592                                                                        
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1                                                                            
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)                                                                            
at java.util.ArrayList.get(ArrayList.java:308)

В моем ListView у меня есть 2 элемента со значениями 13 и 14. Я набираю 4 в текстовом поле поиска, поэтому размер списка должен быть один.

Почему не работает фильтрация? Спасибо за любую помощь.


person BeginnerProgrammer    schedule 28.04.2018    source источник
comment
Используйте LogCat для изучения трассировки стека Java, связанной с вашим сбоем: stackoverflow.com/questions/23353173/   -  person CommonsWare    schedule 28.04.2018
comment
спасибо, я добавляю информацию о logcat в свой пост   -  person BeginnerProgrammer    schedule 28.04.2018
comment
Можете ли вы опубликовать код функции getItemCount   -  person Rishabh Jain    schedule 28.04.2018
comment
Также могу я спросить, почему вы все еще используете ListView вместо RecyclerView.   -  person Rishabh Jain    schedule 28.04.2018


Ответы (1)


Проблема в том, что массив выходит за пределы, потому что getCount() возвращает размер WarrantyList вместо filteredList.

Здесь есть хороший пример того, как обрабатывать два списка: ">Реализация фильтруемых

Но в целом WarrantyAdapter должен использовать filteredList. ItemFilter должен использовать WarrantyList для публикации filteredList.

У меня есть ваш код, работающий в моей среде со следующими изменениями:

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

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

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

и я изменил WarrantyAdapter, чтобы расширить BaseAdapter, а внутри getView я использую filteredList...

person Elletlar    schedule 28.04.2018
comment
да, спасибо, я реализую этот метод, и он работает! - person BeginnerProgrammer; 28.04.2018
comment
Большой! :) :) :) :) - person Elletlar; 28.04.2018