2011-04-14 43 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重写方法。