2011-04-14 44 views
24

我使用的定製ListAdapterListView。我不動態地改變任何東西(查看計數,視圖類型,啓用/禁用,我閱讀其他帖子,但他們改變了代碼)。我必須執行以下操作來觸發異常。向下滾動到列表的底部,然後再次向上滾動。在向上滾動動畫開始時,我得到這個異常。ArrayIndexOutOfBoundsException使用ListAdapter時

04-14 09:41:43.907: ERROR/AndroidRuntime(400): FATAL EXCEPTION: main 
04-14 09:41:43.907: ERROR/AndroidRuntime(400): java.lang.ArrayIndexOutOfBoundsException 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4540) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.widget.AbsListView.trackMotionScroll(AbsListView.java:3370) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.widget.AbsListView.onTouchEvent(AbsListView.java:2233) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.widget.ListView.onTouchEvent(ListView.java:3446) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.View.dispatchTouchEvent(View.java:3885) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1691) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1125) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.app.Activity.dispatchTouchEvent(Activity.java:2096) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1675) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2194) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1878) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.os.Handler.dispatchMessage(Handler.java:99) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.os.Looper.loop(Looper.java:123) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at android.app.ActivityThread.main(ActivityThread.java:3683) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at java.lang.reflect.Method.invoke(Method.java:507) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
04-14 09:41:43.907: ERROR/AndroidRuntime(400):  at dalvik.system.NativeStart.main(Native Method) 

下面是完整的實現。

public class CompanyDetailsAdapter implements ListAdapter { 

    private Context context; 
    private LayoutInflater inflater; 

    private static final class ViewType { 
    private static final int HEADER = 1; 
    private static final int TEXT = 2; 
    private static final int ADDRESS = 3; 
    private static final int REVIEWS = 4; 
    private static final int PRODUCTS = 5; 
    } 

    //all the cells in the order they appear 
    private static final class ViewPositions { 
    private static final int CompanyNameHeader = 0; 
    private static final int CompanyName = 1; 
    private static final int ContactHeader = 2; 
    private static final int Phone = 3; 
    private static final int Website = 4; 
    private static final int AddressHeader = 5; 
    private static final int Address = 6; 
    private static final int DescriptionHeader = 7; 
    private static final int Description = 8; 
    private static final int ReviewsHeader = 9; 
    private static final int Reviews = 10; 
    private static final int ProductsHeader = 11; 
    private static final int Products = 12; 
    } 

    //list of cells by types 
    private static final int[] viewTypes = { 
    ViewType.HEADER,  //0 
    ViewType.TEXT,   //1 
    ViewType.HEADER,  //2 
    ViewType.TEXT,   //3 
    ViewType.TEXT,   //4 
    ViewType.HEADER,  //5 
    ViewType.ADDRESS,  //6 
    ViewType.HEADER,  //7 
    ViewType.TEXT,   //8 
    ViewType.HEADER,  //9 
    ViewType.REVIEWS,  //10 
    ViewType.HEADER,  //11 
    ViewType.PRODUCTS  //12 
    }; 

    //headers 
    private static final int[] headerPositions = { 
    ViewPositions.CompanyNameHeader, 
    ViewPositions.ContactHeader, 
    ViewPositions.AddressHeader, 
    ViewPositions.DescriptionHeader, 
    ViewPositions.ReviewsHeader, 
    ViewPositions.ProductsHeader 
    }; 

    //header resources for position where needed 
    private static final int[] headerResources = { 
    R.string.companyName, 
    0, 
    R.string.contact, 
    0, 
    0, 
    R.string.address, 
    0, 
    R.string.description, 
    0, 
    R.string.reviews, 
    0, 
    R.string.products, 
    0 
    }; 

    //regular texts 
    private static final int[] textPositions = { 
    ViewPositions.CompanyName, 
    ViewPositions.Phone, 
    ViewPositions.Website, 
    ViewPositions.Description, 
    }; 

    public CompanyDetailsAdapter(Context context) { 
    this.context = context; 
    this.inflater = LayoutInflater.from(this.context); 
    } 

    public int getCount() { 
    return viewTypes.length; 
    } 

    public Object getItem(int position) { 
    return null; 
    } 

    public long getItemId(int position) { 
    return position+1; 
    } 

    public int getItemViewType(int position) { 
    return viewTypes[position]; 
    } 

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

    if (arrayContains(headerPositions, position)) { 
     LinearLayout layout = null; 
     TextView txtHeader = null; 
     if (convertView == null) { 
     layout = (LinearLayout)inflater.inflate(R.layout.header_listview,parent, false); 
     } else { 
     layout = (LinearLayout)convertView; 
     } 
     txtHeader = (TextView)layout.findViewById(R.id.txtHeader); 
     String value = context.getText(headerResources[position]).toString(); 
     txtHeader.setText(value); 
     return layout; 
    } else if (arrayContains(textPositions, position)) { 
     TextView txtText = null; 
     LinearLayout layout = null; 
     Company c = Company.getSelectedCompany(); 
     if (convertView == null) { 
     layout = (LinearLayout)inflater.inflate(R.layout.default_text,parent, false); 
     } else { 
     layout = (LinearLayout)convertView; 
     } 
     txtText = (TextView)layout.findViewById(R.id.txtNormalText); 
     switch (position) { 
     case ViewPositions.CompanyName: 
      txtText.setText(c.getName()); 
      break; 
     case ViewPositions.Phone: 
      txtText.setText(c.getPhone()); 
      break; 
     case ViewPositions.Website: 
      txtText.setText(c.getWebsiteString()); 
      break; 
     case ViewPositions.Description: 
      txtText.setText(c.getDescription()); 
      break; 
     } 
     return layout; 
    } else { 
     View v = null; 
     //LinearLayout layout = null; 
     Company company = Company.getSelectedCompany(); 
     switch (position) { 
     case ViewPositions.Address: 
      if (convertView == null) 
      v = (LinearLayout)inflater.inflate(R.layout.adress, parent,false); 
      else 
      v = (LinearLayout)convertView; 

      TextView txtAddress = (TextView)v.findViewById(R.id.txtAddress); 
      txtAddress.setText(String.format("%s %s %s", company.getCity(), 
              company.getStreet(), company.getPostalCode())); 
      break; 
     case ViewPositions.Products: 
      if (convertView == null) 
      v = (LinearLayout)inflater.inflate(R.layout.products, parent,false); 
      else 
      v = (LinearLayout)convertView; 

      v = (LinearLayout)inflater.inflate(R.layout.products, parent,false); 
      TextView txtNumProducts = (TextView)v.findViewById(R.id.txtNumProducts); 
      txtNumProducts.setText(String.valueOf(company.getNrProducts())); 
      break; 
     case ViewPositions.Reviews: 
      if (convertView == null) 
      v = (LinearLayout)inflater.inflate(R.layout.reviews, parent,false); 
      else 
      v = (LinearLayout)convertView; 

      v = (LinearLayout)inflater.inflate(R.layout.reviews, parent,false); 
      TextView txtNumReviews = (TextView)v.findViewById(R.id.txtNumReviews); 
      txtNumReviews.setText(String.valueOf(company.getNrReviews())); 
      RatingBar rating = (RatingBar)v.findViewById(R.id.ratAvg); 
      rating.setRating(company.getAvgRating()); 
      break; 
     } 
     return v; 
    } 
    } 

    public int getViewTypeCount() { 
    return 5; 
    } 

    public boolean hasStableIds() { 
    return true; 
    } 

    public boolean isEmpty() { 
    return false; 
    } 

    public void registerDataSetObserver(DataSetObserver arg0) { 
    } 

    public void unregisterDataSetObserver(DataSetObserver arg0) { 
    } 

    public boolean areAllItemsEnabled() { 
    return false; 
    } 

    public boolean isEnabled(int position) { 
    if (arrayContains(headerPositions, position)) return false; 
    return true; 
    } 

    private Boolean arrayContains(int[] array, int element) { 
    for (int i=0; i<array.length; i++) { 
     if (array[i] == element) return true; 
    } 
    return false; 
    } 


} 

我附源到Android 2.3.3庫從here。我沒有發現其他的堆棧跟蹤沒有顯示出來。大家都知道ListView可以回收視圖。有一些類型的集合可以保存這些循環的視圖。當視圖消失時,它被添加到那裏(我認爲)。這發生在at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:4540)某處在這裏它給了我一個例外,即某些事情是超出界限的。我沒有絲毫的線索。但我沒有耐心去調試另外1000行代碼,所以我想現在我會使用ScrollView。


似乎在這條線:(AbsListView.class:4540個mScrapViews[viewType].add(scrap); mScrapViews是private ArrayList<View>[] mScrapViews;類型是View類型的列表數組我可以嘗試觀看viewTypescrap變量,但它。說errors_during_evaluation也許太愚蠢評估

+0

你可以發佈無法運行的代碼部分嗎? – 2011-04-14 06:54:52

+0

當然我可以發佈所有的代碼,我不知道什麼是錯的 – 2011-04-14 06:59:02

+0

嘗試一步一步地調試你的代碼。這是一個很好的開始:android.widget.ListView.onTouchEvent(ListView.java:3446) – 2011-04-14 07:00:30

回答

76

發現問題。視圖類型必須從0開始,我的從1開始。

Android正在使用我提供的視圖類型來通過索引訪問數組。 SomeArraySomewhere[myViewType]此數組的大小可能等於視圖類型的數量。因此,這意味着我必須在0

+0

謝謝!我有同樣的麻煩,並找不到解決方案的原因 – 2016-05-27 13:08:26

+0

+1。但是你究竟在哪裏發現了這個'SomeArraySomewhere []'?在適配器的源代碼? – 2016-09-17 05:36:30

+0

對不起,這是很久以前,我不記得了 – 2016-09-18 15:38:19

3

這可能是position是:。

  • 一個:null
  • b:higher then the amount of headerResources

在這一行(getView):

String value = context.getText(headerResources[position]).toString(); 

先學會調試:這裏是一個nice video tutorial

+0

在上面的答案中觀看視頻以瞭解調試情況:-) – 2011-04-14 10:12:36

5

開始我的看法類型更改此:

public int getViewTypeCount() 
{ 
    return 2; 
} 

來幫我:

public int getViewTypeCount() 
{ 
    return 3; 
} 

說明:

起初我有2視圖類型,但後來在實現中,我添加了第三種。 我開始得到這個異常,因爲我忘記更新方法getViewTypeCount()返回3而不是2。

希望這可以幫助別人:)

1

究其原因,很可能是因爲該getItemViewType方法返回錯誤的值! listview中的每一行都是一個View。雖然scrioling getItemViewType達不止View的數量。

該怎麼辦?如何避免問題?

首先確定在列表視圖的視圖(行),其被示出first.While滾動使用moduler方程

@Override 
public int getItemViewType(int position) { 
    return choseType(position);//function to use modular equation 
} 
@Override 
public int getViewTypeCount() { 
    return 10; 
} 

在本例中有10個圖(10行)。

private int choseType(int position){ 
    if(position%10==0) 
     return 0; 
    else if(position%10==1) 
     return 1; 
    else if(position%10==2) 
     return 2; 
    else if(position%10==3) 
     return 3; 
    else if(position%10==4) 
     return 4; 
    else if(position%10==5) 
     return 5; 
    else if(position%10==6) 
     return 6; 
    else if(position%10==7) 
     return 7; 
    else if(position%10==8) 
     return 8; 
    else 
     return 9; 


} 

重要

有些用戶對計算器該方法

公衆詮釋getViewTypeCount()和公衆詮釋getItemViewType(INT位置)修正像Tooglebutton另外一個問題提到的全自動實現國家檢查真的在scrooling .. 那是大錯了。如果你不想自動enbale上scrool只是做

toogleButton.setChecked(false); 

上getView重寫方法。

相關問題