Мне нужно несколько viewHolders для ExpandableListView?

Я неправильно использую этот зритель? Я получаю NPE на линии 165. Есть ли очевидная причина, почему я не хватает? Нужен ли мне аудитор группы и дочерний зритель, если я использую expandablelistview? Я выделил строку 165, чтобы попытаться облегчить глаза.

большое спасибо

Мой расширенный список, который получает NPE:

public class MyExpandableListAdapter extends BaseExpandableListAdapter { private Context mContext; private ArrayList<ContactNameItems> mListDataHeader; private ArrayList<Boolean> phoneNumberCheckStates; private ArrayList<String> selectedNumbers; private HashMap<String, List<ContactPhoneItems>> mListDataChild; private ViewHolder mViewHolder; public MyExpandableListAdapter(Context context, ArrayList<ContactNameItems> listDataHeader, HashMap<String, List<ContactPhoneItems>> listDataChild, ArrayList<String> listOfNumbers) { mContext = context; mListDataHeader = listDataHeader; mListDataChild = listDataChild; selectedNumbers = listOfNumbers; } @Override public int getGroupCount() { return mListDataHeader.size(); } @Override public ContactNameItems getGroup(int groupPosition) { return mListDataHeader.get(groupPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { String contactName = getGroup(groupPosition).getName(); Bitmap contactImage = getGroup(groupPosition).getImage(); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.contact_name_item, null); mViewHolder = new ViewHolder(); mViewHolder.mContactName = (TextView) convertView .findViewById(R.id.lblListHeader); mViewHolder.mContactImage = (ImageView) convertView .findViewById(R.id.ivContactPhoto); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } if (contactImage != null) { mViewHolder.mContactImage.setImageBitmap(contactImage); } else { mViewHolder.mContactImage.setImageResource(R.drawable.default_contact); } mViewHolder.mContactName.setText(contactName); return convertView; } @Override public int getChildrenCount(int groupPosition) { return mListDataChild.get(mListDataHeader.get(groupPosition).getName()) .size(); } @Override public ContactPhoneItems getChild(int groupPosition, int childPosition) { return mListDataChild.get(mListDataHeader.get(groupPosition).getName()) .get(childPosition); } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { String numberText = getChild(groupPosition, childPosition).getNumber(); String typeText = getChild(groupPosition, childPosition).getPhoneType(); final int mGroupPosition = groupPosition; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) this.mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.contact_detail_item, null); mViewHolder = new ViewHolder(); mViewHolder.mPhoneNumber = (TextView) convertView .findViewById(R.id.tv_phone_number); mViewHolder.mPhoneType = (TextView) convertView .findViewById(R.id.tv_phone_type); mViewHolder.mCheckBox = (CheckBox) convertView .findViewById(R.id.checkBox); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } mViewHolder.mPhoneNumber.setText(numberText); mViewHolder.mPhoneType.setText(typeText); phoneNumberCheckStates = new ArrayList<Boolean>(); for (int i = 0; i < mListDataChild.size(); i++) { phoneNumberCheckStates.add(false); } if (phoneNumberCheckStates.get(childPosition)) { mViewHolder.mCheckBox.setChecked(true); } else { mViewHolder.mCheckBox.setChecked(false); } mViewHolder.mCheckBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /*this is line 165*/ if (mViewHolder.mCheckBox.isChecked()) { /*this is line 165*/ phoneNumberCheckStates.set(childPosition, true); selectedNumbers.add(mListDataChild .get(mListDataHeader.get(mGroupPosition).getName()) .get(childPosition).getNumber()); } else { phoneNumberCheckStates.set(childPosition, false); selectedNumbers.remove(mListDataChild .get(mListDataHeader.get(mGroupPosition).getName()) .get(childPosition).getNumber()); } } }); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } @Override public boolean hasStableIds() { return false; } public ArrayList<Boolean> getCheckedNumbers() { return phoneNumberCheckStates; } public ArrayList<String> getSelectedNumbers() { return selectedNumbers; } private class ViewHolder { TextView mContactName; TextView mPhoneNumber; TextView mPhoneType; ImageView mContactImage; CheckBox mCheckBox; } } 

Если это помогает, вот Log:

 01-25 04:34:31.695: E/AndroidRuntime(7074): FATAL EXCEPTION: main 01-25 04:34:31.695: E/AndroidRuntime(7074): java.lang.NullPointerException 01-25 04:34:31.695: E/AndroidRuntime(7074): at com.psesto.journeysend.contactpicker.MyExpandableListAdapter$1.onClick(MyExpandableListAdapter.java:165) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.view.View.performClick(View.java:4204) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.widget.CompoundButton.performClick(CompoundButton.java:100) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.view.View$PerformClick.run(View.java:17355) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.os.Handler.handleCallback(Handler.java:725) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.os.Handler.dispatchMessage(Handler.java:92) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.os.Looper.loop(Looper.java:137) 01-25 04:34:31.695: E/AndroidRuntime(7074): at android.app.ActivityThread.main(ActivityThread.java:5041) 01-25 04:34:31.695: E/AndroidRuntime(7074): at java.lang.reflect.Method.invokeNative(Native Method) 01-25 04:34:31.695: E/AndroidRuntime(7074): at java.lang.reflect.Method.invoke(Method.java:511) 01-25 04:34:31.695: E/AndroidRuntime(7074): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 01-25 04:34:31.695: E/AndroidRuntime(7074): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 01-25 04:34:31.695: E/AndroidRuntime(7074): at dalvik.system.NativeStart.main(Native Method) 

У вас есть одна ссылка ViewHolder в вашем Adapter для всех ваших Views . Это не имеет никакого смысла, потому что каждый вид в списке имеет свой собственный экземпляр ViewHolder который вы получаете через View.getTag() .

Вы можете установить int[] с необходимыми позициями в качестве тега CheckBox

  int[] positions = new int[2]; positions[0] = childPosition; positions[1] = groupPosition; mViewHolder.mCheckBox.setTag(positions); 

И в onClick()

  CheckBox box = (CheckBox) v; int[] posTag = (int[]) v.getTag(); 

Затем у вас есть CheckBox для состояния и позиции для остальных

Я принял ответ Таллия288, потому что он указал мне в правильном направлении. Вот изменение кода, из-за которого все работает:

 public class MyExpandableListAdapter extends BaseExpandableListAdapter { private Context mContext; private ArrayList<ContactNameItems> mListDataHeader; private ArrayList<String> selectedNumbers; private HashMap<String, List<ContactPhoneItems>> mListDataChild; private ChildViewHolder childViewHolder; private GroupViewHolder groupViewHolder; public MyExpandableListAdapter(Context context, ArrayList<ContactNameItems> listDataHeader, HashMap<String, List<ContactPhoneItems>> listDataChild, ArrayList<String> listOfNumbers) { mContext = context; mListDataHeader = listDataHeader; mListDataChild = listDataChild; selectedNumbers = listOfNumbers; } @Override public int getGroupCount() { return mListDataHeader.size(); } @Override public ContactNameItems getGroup(int groupPosition) { return mListDataHeader.get(groupPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { String contactName = getGroup(groupPosition).getName(); Bitmap contactImage = getGroup(groupPosition).getImage(); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.contact_name_item, null); groupViewHolder = new GroupViewHolder(); groupViewHolder.mContactName = (TextView) convertView .findViewById(R.id.lblListHeader); groupViewHolder.mContactImage = (ImageView) convertView .findViewById(R.id.ivContactPhoto); convertView.setTag(groupViewHolder); } else { groupViewHolder = (GroupViewHolder) convertView.getTag(); } if (contactImage != null) { groupViewHolder.mContactImage.setImageBitmap(contactImage); } else { groupViewHolder.mContactImage .setImageResource(R.drawable.default_contact); } groupViewHolder.mContactName.setText(contactName); return convertView; } @Override public int getChildrenCount(int groupPosition) { return mListDataChild.get(mListDataHeader.get(groupPosition).getName()) .size(); } @Override public ContactPhoneItems getChild(int groupPosition, int childPosition) { return mListDataChild.get(mListDataHeader.get(groupPosition).getName()) .get(childPosition); } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { String numberText = getChild(groupPosition, childPosition).getNumber(); String typeText = getChild(groupPosition, childPosition).getPhoneType(); final int mGroupPosition = groupPosition; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) this.mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.contact_detail_item, null); childViewHolder = new ChildViewHolder(); childViewHolder.mPhoneNumber = (TextView) convertView .findViewById(R.id.tv_phone_number); childViewHolder.mPhoneType = (TextView) convertView .findViewById(R.id.tv_phone_type); childViewHolder.mCheckBox = (CheckBox) convertView .findViewById(R.id.checkBox); childViewHolder.mCheckBox.setOnCheckedChangeListener(checkListener); convertView.setTag(childViewHolder); } else { childViewHolder = (ChildViewHolder) convertView.getTag(); } childViewHolder.mPhoneNumber.setText(numberText); childViewHolder.mPhoneType.setText(typeText); ContactPhoneItems cpi = getChild(mGroupPosition, childPosition); childViewHolder.mCheckBox.setTag(cpi); childViewHolder.mCheckBox.setChecked(cpi.getSelected()); // for managing the state of the boolean // array according to the state of the // CheckBox childViewHolder.mCheckBox .setOnClickListener(new View.OnClickListener() { String contactNumber = mListDataChild .get(mListDataHeader.get(mGroupPosition).getName()) .get(childPosition).getNumber(); public void onClick(View v) { boolean isChecked = ((CheckBox) v).isChecked(); if (isChecked) { selectedNumbers.add(contactNumber); } else { selectedNumbers.remove(contactNumber); } getChild(mGroupPosition, childPosition).setSelected(isChecked); notifyDataSetChanged(); } }); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } @Override public boolean hasStableIds() { return false; } public ArrayList<String> getSelectedNumbers() { return selectedNumbers; } public final class GroupViewHolder { TextView mContactName; ImageView mContactImage; } public final class ChildViewHolder { TextView mPhoneNumber; TextView mPhoneType; CheckBox mCheckBox; } OnCheckedChangeListener checkListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { ContactPhoneItems c = (ContactPhoneItems) buttonView.getTag(); c.setSelected(isChecked); } }; } 

Это происходит, если представление Child повторно использует представление Group , а также ViewHolder . Очевидно, что он не может найти mCheckBox в строке 165, потому что он не был установлен.
Просто добавив флаг в ViewHolder , чтобы проверить, является ли это ViewHolder для Child , можно решить вашу проблему. Здесь нет необходимости иметь два вида ViewHolder .
Надежда помогает

Intereting Posts
Пределы android.graphics.path Получение электронной почты из аккаунта Google Plus в приложении Android Попытка написать базу данных только для чтения … но я не Как программно проверить, работает ли активность в полноэкранном режиме? Как реализовать горизонтальную прокрутку для панели инструментов в android? Обратное проектирование: Извлечение изображений / лист спрайтов из apk Выровнять текст до края метки в ScrollView в киви В android sdk1.5 где я могу найти свой Sqlite Db в моей системе Сохранить несколько изображений на Android Как настроить реакцию родной андроидной библиотеки на использование npm, установленную на основе реакции? Как создать уведомление, подобное приложению Play Music от Google Получение типа столбца в SQLite В чем разница между инструментами платформы и инструментами SDK в разработке Android? AsyncTask's doInBackground (Params … params) Изменение текста в тексте Android ListView по выбору