2013-03-04 19 views
8

Jestem początkującym na Androidzie.filtrowanie niestandardowego adaptera IndexOutOfBoundsException

Mój niestandardowy adapter powoduje wyjątek podczas filtrowania.

Oto mój kod. prywatny klasa DeptAdapter rozciąga ArrayAdapter realizuje filtrować {

private ArrayList<Dept> items; 
    private ArrayList<Dept> mOriginalValues; 

    public DeptAdapter(Context context, int textViewResourceId, ArrayList<Dept> items) { 
      super(context, textViewResourceId, items); 
      this.items = items; 
    } 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View v = convertView; 

     if (v == null) { 
      LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = vi.inflate(R.layout.item_listview_2line, null); 
     } 
     Dept d = items.get(position); 
     if (d != null) { 
       TextView tt = (TextView) v.findViewById(R.id.toptext); 
       TextView bt = (TextView) v.findViewById(R.id.bottomtext); 
       if (tt != null){ 
        tt.setText(d.dept_nm);        
       } 
       if(bt != null){ 
        bt.setText(d.dept_cd); 
       } 
     } 
     return v; 
    } 

    @Override 
    public Filter getFilter() { 
     Filter filter = new Filter() { 

      @SuppressWarnings("unchecked") 
      @Override 
      protected void publishResults(CharSequence constraint,FilterResults results) { 

       items = (ArrayList<Dept>) results.values; // has the filtered values 
       if (results.count > 0) { 
        notifyDataSetChanged(); 
       } else { 
        notifyDataSetInvalidated(); 
       } 
      } 

      } 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults results = new FilterResults();  // Holds the results of a filtering operation in values 
       ArrayList<Dept> FilteredArrList = new ArrayList<Dept>(); 

       if (mOriginalValues == null) { 
        mOriginalValues = new ArrayList<Dept>(items); // saves the original data in mOriginalValues 
       } 

       if (constraint == null || constraint.length() == 0) { 

        // set the Original result to return 
        results.count = mOriginalValues.size(); 
        results.values = mOriginalValues; 
       } else { 
        constraint = constraint.toString().toLowerCase(); 
        for (int i = 0; i < mOriginalValues.size(); i++) { 
         Dept d = mOriginalValues.get(i); 
         if (d.dept_cd.toLowerCase().startsWith(constraint.toString()) || d.dept_nm.toLowerCase().startsWith(constraint.toString())) { 
          FilteredArrList.add(d); 
         } 
        } 
        // set the Filtered result to return 
        results.count = FilteredArrList.size(); 
        results.values = FilteredArrList; 
       } 
       return results; 
      } 
     }; 
     return filter; 
    } 
} 

class Dept 
{ 
    String dept_cd; 
    String dept_nm; 
    public Dept(String dept_cd, String dept_nm) 
    { 
     this.dept_cd = dept_cd; 
     this.dept_nm = dept_nm; 
    } 
    public String toString() 
    { 
     return this.dept_nm+ "(" + this.dept_cd +")" ; 
    } 
} 

pomóż mi ktoś .... Nie mogę zrozumieć, dlaczego metoda getView() została wywołana więcej niż items.size()

+0

proszę dodać kompletny kod DeptAdapter klasy i logcat wyjściu –

+1

Chcę również kod z dwóch metod getCount() i GetItem (int pozycja) –

Odpowiedz

16

Pamiętaj że getView() wyśle ​​zapytanie o wielkości przedmiotów, że superclass Has, który w tej chwili, jest to, czego pierwotnie podał podczas wywoływania konstruktora nadklasy,

super(context, textViewResourceId, items); 

Dlatego superklasa nie wie, że zmieniłeś rozmiar po przefiltrowaniu. Oznacza to, że getCount() zwróci pierwotny rozmiar tablicy, co jest zrozumiałe większe niż tablica filtrowana.

Oznacza to, że należy zastąpić metodę getCount() więc masz pewność, że wracasz rzeczywistą poprawny rozmiar:

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

Należy także zmienić innych metod związanych z operacjami listy (takich jak uzyskiwanie) jeśli zamierzasz ich używać. Np

@Override 
public Dept getItem (int pos){ 
    return items.get(pos); 
} 
+1

Dziękuję bardzo! Twoja odpowiedź całkowicie rozwiązała mój problem. – user1788012

+1

Uratowałem cały dzień – Nabin

+1

Miałem ten sam problem i twoje rozwiązanie działało również dla mnie. Dzięki! – user2151486

0

Brakuje getCount() metodę spojrzeć na to demo

Mam nadzieję, że będzie to pomocne!

0
private ArrayList<Dept> items; 
    private ArrayList<Dept> mOriginalValues; 

    public DeptAdapter(Context context, int textViewResourceId, ArrayList<Dept> items) { 
      super(context, textViewResourceId, items); 
      this.items = items; 
      this.mOriginalValues=items; //add this line in your code 
    } 
+0

'mOriginalValues' jest symbolem zastępczym podczas gdy filtrowanie jest na miejscu. Nie musi trzymać się przedmiotów od samego początku. –

+0

if (mOriginalValues ​​== null) {mOriginalValues ​​= new ArrayList (elementy); // zapisuje oryginalne dane w mOriginalValues} tutaj widzisz pierwsze użycie, a następnie inicjalizujesz bro @ A - C – QuokMoon

+0

Został zainicjowany, jeśli jest pusty i tam zapisujesz kopię. Przypisanie do konstruktora jest dobrym zabezpieczeniem przed awarią, ale sprawdzanie "null" już istnieje, gdy filtrujesz z jakiegoś powodu. 'this.mOriginalValues ​​= items;' nie jest potrzebne w konstruktorze. –

1

Trzeba dodać to metody dla lepszej wydajności:

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

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

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