Я использую пользовательский ListAdapter
для ListView
. Я ничего не меняю динамически (количество просмотров, типы просмотров, включено/отключено, я читаю другие сообщения, но они что-то меняют из кода). Я должен сделать следующее, чтобы вызвать исключение. Прокрутите вниз до конца списка и после этого снова прокрутите список. В начале анимации прокрутки я получаю это исключение.
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 из здесь. Я ничего не узнал, что трассировка стека не показала мне. Как вы все знаете, 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
. Я могу попытаться посмотреть viewType
и scrap
, но он говорит errors_during_evaluation
. Вероятно, слишком тупой, чтобы оценить.