ExpandableListAdapter onClickListener,调用notifyDataSetChanged()
ExpandableListAdapter onClickListener, call notifyDataSetChanged()
我有一个使用 onclickListener 更改父文本的自定义适配器,我不知道如何让 notifyDataSetChanged 方法在适配器中工作。
应该发生的是我有一个可扩展的视图,当您单击子项中的按钮时,它会使用子项的文本更新父项...
这是应该发生的事情的图片示例。
在点击按钮之前使用这个:
点击按钮后使用:
"Choose an Ingredient" 更改为 "Rice, cups" 或单击的任何内容
所以在我显示的代码中,单击按钮后它应该更新父级,它会这样做,然后刷新视图,但由于某种原因我不能这样做?
这是我的代码,提前致谢!
package com.example.andrew.mypantry;
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.HashMap;
import java.util.List;
/**
* Created by andrew on 7/1/2015.
*/
public class IngExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader; //header titles
//child data in format of <header title, child title>
private HashMap<String, List<String>> listDataChild;
public IngExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listDataChild) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listDataChild;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
private void test() {
//notifyDataSetChanged();
//super.notifyDataSetChanged();
//this.notifyDataSetChanged();
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_item, null);
}
TextView txtListChild = (TextView) convertView.findViewById(R.id.ingredientContentTextView);
txtListChild.setText(childText);
//handle button
Button ingredientButton = (Button)convertView.findViewById(R.id.useIngredient_button);
ingredientButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//change header to ingredient selected
listDataHeader.set(groupPosition, childText);
//test();
}
});
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPostion) {
return this.listDataHeader.get(groupPostion);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if(convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_group, null);
}
//handle textView
final TextView listHeader = (TextView) convertView.findViewById(R.id.ingredientGroupTextView);
listHeader.setTypeface(null, Typeface.BOLD);
listHeader.setText(headerTitle);
//handle button
Button deleteButton = (Button)convertView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//remove item from list
Log.d("TESTING", "item should be removed");
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
而不是使用 notifyDataSetChanged();
从数据来源创建接口并实现它是您的适配器,然后更改该接口函数中 parent 的值,如 getChildView()
在每个 child 之后被调用,它将更新您的列表视图 Parent。检查并验证我有同样的问题
假设您要将数据从 Adapter 传输到 Adapter
adapter.java
public interface data { public void dataMethod(String data); }
并在adapter
中实现这个方法
public void dataMethod(String data) {
this.data = data;
}
从 getChildView() 调用 dataMethod() 并更新字符串,如我所示
并在适配器的getViewChild方法中设置数据
我认为问题出在您使用的数据结构上。您将 children 的列表分配给散列 table 中的 parent 的名称。当 parent 的名称在 parent 列表中更改时,散列 table 中的旧 children 赋值不再有效。
我建议您对 listDataChild
字段使用 SparseArray<List<String>>
或 List<List<String>>
。它将组位置直接映射到 children 列表。因此,在 listDataHeader
中更改 parent 的名称不会破坏数据一致性,因为组位置将保持不变。现在您应该可以安全地使用 notifyDataSetChanged()
方法来更新 headers.
希望对您有所帮助。
正如@beworker 已经提到的,您不应该将 children 存储在 HashMap
中。请改用 ArrayList
并通过组索引访问 children。这就是您可以更改适配器的方式。作为奖励,我实施了群组移除。
public class IngExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader; //header titles
private List<List<String>> listDataChild;
public IngExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listDataChild) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = new ArrayList<List<String>>();
for (String header : listDataHeader) {
List<String> children = listDataChild.get(header);
if (children == null) {
children = Collections.emptyList();
}
this.listDataChild.add(children);
}
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(groupPosition).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView,
ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(this.context);
convertView =
layoutInflater.inflate(R.layout.ingredient_list_item, null);
}
TextView txtListChild =
(TextView) convertView.findViewById(R.id.ingredientContentTextView);
txtListChild.setText(childText);
//handle button
Button ingredientButton =
(Button) convertView.findViewById(R.id.useIngredient_button);
ingredientButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//change header to ingredient selected
listDataHeader.set(groupPosition, childText);
notifyDataSetChanged();
}
});
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(groupPosition).size();
}
@Override
public Object getGroup(int groupPostion) {
return this.listDataHeader.get(groupPostion);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if(convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(this.context);
convertView =
layoutInflater.inflate(R.layout.ingredient_list_group, null);
}
//handle textView
final TextView listHeader =
(TextView) convertView.findViewById(R.id.ingredientGroupTextView);
listHeader.setTypeface(null, Typeface.BOLD);
listHeader.setText(headerTitle);
//handle button
Button deleteButton = (Button) convertView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//remove item from list
Log.d("TESTING", "item should be removed");
this.listDataHeader.remove(groupPosition);
this.listDataChild.remove(groupPosition);
notifyDataSetChanged();
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
这是完全可行的解决方案。主要思想 - 不要在 Adapter
中使用 OnClickListener
,而必须使用 ExpandableListView.setOnChildClickListener()
。
MyFragment.java
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
public class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
String[][] data = {
{"Rice, cups", "Chiken, breasts", "Milk, gallons", "Beans, cups"},
{"Orange, lemon", "Tomato, potato", "Onion, garlic"},
{"Apple, pinapple", "Grapes, pear", "Cherry, berry", "Banana, strawberry", "Peach, apricot"},
};
final ChoiceAdapter adapter = new ChoiceAdapter(data);
final ExpandableListView listView = new ExpandableListView(inflater.getContext());
listView.setGroupIndicator(null);
listView.setAdapter(adapter);
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
adapter.selectChild(groupPosition, childPosition);
listView.collapseGroup(groupPosition);
// NOTE you even don't need to call notifyDataSetChanged() if you call collapseGroup()
// adapter.notifyDataSetChanged();
return true;
}
});
return listView;
}
}
ChoiceAdapter.java
import android.graphics.Typeface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.Arrays;
public class ChoiceAdapter extends BaseExpandableListAdapter {
private final String[][] mData;
private final int[] mChoice;
public ChoiceAdapter(String[][] data) {
mData = data;
mChoice = new int[data.length];
Arrays.fill(mChoice, -1);
}
@Override
public int getGroupCount() {
return mData.length;
}
@Override
public int getChildrenCount(int groupPosition) {
return mData[groupPosition].length;
}
@Override
public Integer getGroup(int groupPosition) {
return mChoice[groupPosition];
}
@Override
public String getChild(int groupPosition, int childPosition) {
return mData[groupPosition][childPosition];
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
// TODO inflate layout from xml instead
convertView = new TextView(parent.getContext());
}
// TODO use ViewHolder pattern instead
TextView textView = (TextView) convertView;
textView.setTypeface(null, Typeface.BOLD);
int childPosition = getGroup(groupPosition);
if (childPosition < 0) {
textView.setText("Choose an ingredient");
} else {
textView.setText(getChild(groupPosition, childPosition));
}
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
// TODO inflate layout from xml instead
convertView = new TextView(parent.getContext());
}
// TODO use ViewHolder pattern instead
TextView textView = (TextView) convertView;
textView.setText(getChild(groupPosition, childPosition));
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public void selectChild(int groupPosition, int childPosition) {
mChoice[groupPosition] = childPosition;
}
@Override
public long getGroupId(int groupPosition) { return 0; }
@Override
public long getChildId(int groupPosition, int childPosition) { return 0; }
@Override
public boolean hasStableIds() { return false; }
}
正如 beworker 提到的,您的问题来自使用错误的数据结构,这就是您的应用程序崩溃的原因。您正在使用 header 标题作为哈希映射的键,当您修改 listDataHeader
中的标题时,修改会正确应用于它,但不适用于哈希映射内的键 object。这意味着您的 children 仍然存在于哈希图中的旧标题键下,而新标题键的值是 null
。因此,当您调用
时,您将得到一个 NullPointerException
this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
因为
this.listDataChild.get(this.listDataHeader.get(groupPosition))
returns Null
解决方案是对 header 个标题使用 ArrayList,对 children 使用 ArrayList>。这两个 arrayLists 中的键是您的组索引。
我有一个使用 onclickListener 更改父文本的自定义适配器,我不知道如何让 notifyDataSetChanged 方法在适配器中工作。
应该发生的是我有一个可扩展的视图,当您单击子项中的按钮时,它会使用子项的文本更新父项...
这是应该发生的事情的图片示例。
在点击按钮之前使用这个:
点击按钮后使用:
"Choose an Ingredient" 更改为 "Rice, cups" 或单击的任何内容
所以在我显示的代码中,单击按钮后它应该更新父级,它会这样做,然后刷新视图,但由于某种原因我不能这样做?
这是我的代码,提前致谢!
package com.example.andrew.mypantry;
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.HashMap;
import java.util.List;
/**
* Created by andrew on 7/1/2015.
*/
public class IngExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader; //header titles
//child data in format of <header title, child title>
private HashMap<String, List<String>> listDataChild;
public IngExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listDataChild) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listDataChild;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
private void test() {
//notifyDataSetChanged();
//super.notifyDataSetChanged();
//this.notifyDataSetChanged();
}
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild,
View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition,childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_item, null);
}
TextView txtListChild = (TextView) convertView.findViewById(R.id.ingredientContentTextView);
txtListChild.setText(childText);
//handle button
Button ingredientButton = (Button)convertView.findViewById(R.id.useIngredient_button);
ingredientButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//change header to ingredient selected
listDataHeader.set(groupPosition, childText);
//test();
}
});
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPostion) {
return this.listDataHeader.get(groupPostion);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if(convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.ingredient_list_group, null);
}
//handle textView
final TextView listHeader = (TextView) convertView.findViewById(R.id.ingredientGroupTextView);
listHeader.setTypeface(null, Typeface.BOLD);
listHeader.setText(headerTitle);
//handle button
Button deleteButton = (Button)convertView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//remove item from list
Log.d("TESTING", "item should be removed");
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
而不是使用 notifyDataSetChanged();
从数据来源创建接口并实现它是您的适配器,然后更改该接口函数中 parent 的值,如 getChildView()
在每个 child 之后被调用,它将更新您的列表视图 Parent。检查并验证我有同样的问题
假设您要将数据从 Adapter 传输到 Adapter
adapter.java
public interface data { public void dataMethod(String data); }
并在adapter
public void dataMethod(String data) {
this.data = data;
}
从 getChildView() 调用 dataMethod() 并更新字符串,如我所示
并在适配器的getViewChild方法中设置数据
我认为问题出在您使用的数据结构上。您将 children 的列表分配给散列 table 中的 parent 的名称。当 parent 的名称在 parent 列表中更改时,散列 table 中的旧 children 赋值不再有效。
我建议您对 listDataChild
字段使用 SparseArray<List<String>>
或 List<List<String>>
。它将组位置直接映射到 children 列表。因此,在 listDataHeader
中更改 parent 的名称不会破坏数据一致性,因为组位置将保持不变。现在您应该可以安全地使用 notifyDataSetChanged()
方法来更新 headers.
希望对您有所帮助。
正如@beworker 已经提到的,您不应该将 children 存储在 HashMap
中。请改用 ArrayList
并通过组索引访问 children。这就是您可以更改适配器的方式。作为奖励,我实施了群组移除。
public class IngExpandableListAdapter extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader; //header titles
private List<List<String>> listDataChild;
public IngExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listDataChild) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = new ArrayList<List<String>>();
for (String header : listDataHeader) {
List<String> children = listDataChild.get(header);
if (children == null) {
children = Collections.emptyList();
}
this.listDataChild.add(children);
}
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(groupPosition).get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView,
ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(this.context);
convertView =
layoutInflater.inflate(R.layout.ingredient_list_item, null);
}
TextView txtListChild =
(TextView) convertView.findViewById(R.id.ingredientContentTextView);
txtListChild.setText(childText);
//handle button
Button ingredientButton =
(Button) convertView.findViewById(R.id.useIngredient_button);
ingredientButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//change header to ingredient selected
listDataHeader.set(groupPosition, childText);
notifyDataSetChanged();
}
});
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(groupPosition).size();
}
@Override
public Object getGroup(int groupPostion) {
return this.listDataHeader.get(groupPostion);
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if(convertView == null) {
LayoutInflater layoutInflater = LayoutInflater.from(this.context);
convertView =
layoutInflater.inflate(R.layout.ingredient_list_group, null);
}
//handle textView
final TextView listHeader =
(TextView) convertView.findViewById(R.id.ingredientGroupTextView);
listHeader.setTypeface(null, Typeface.BOLD);
listHeader.setText(headerTitle);
//handle button
Button deleteButton = (Button) convertView.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//remove item from list
Log.d("TESTING", "item should be removed");
this.listDataHeader.remove(groupPosition);
this.listDataChild.remove(groupPosition);
notifyDataSetChanged();
}
});
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
这是完全可行的解决方案。主要思想 - 不要在 Adapter
中使用 OnClickListener
,而必须使用 ExpandableListView.setOnChildClickListener()
。
MyFragment.java
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
public class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
String[][] data = {
{"Rice, cups", "Chiken, breasts", "Milk, gallons", "Beans, cups"},
{"Orange, lemon", "Tomato, potato", "Onion, garlic"},
{"Apple, pinapple", "Grapes, pear", "Cherry, berry", "Banana, strawberry", "Peach, apricot"},
};
final ChoiceAdapter adapter = new ChoiceAdapter(data);
final ExpandableListView listView = new ExpandableListView(inflater.getContext());
listView.setGroupIndicator(null);
listView.setAdapter(adapter);
listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
adapter.selectChild(groupPosition, childPosition);
listView.collapseGroup(groupPosition);
// NOTE you even don't need to call notifyDataSetChanged() if you call collapseGroup()
// adapter.notifyDataSetChanged();
return true;
}
});
return listView;
}
}
ChoiceAdapter.java
import android.graphics.Typeface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.Arrays;
public class ChoiceAdapter extends BaseExpandableListAdapter {
private final String[][] mData;
private final int[] mChoice;
public ChoiceAdapter(String[][] data) {
mData = data;
mChoice = new int[data.length];
Arrays.fill(mChoice, -1);
}
@Override
public int getGroupCount() {
return mData.length;
}
@Override
public int getChildrenCount(int groupPosition) {
return mData[groupPosition].length;
}
@Override
public Integer getGroup(int groupPosition) {
return mChoice[groupPosition];
}
@Override
public String getChild(int groupPosition, int childPosition) {
return mData[groupPosition][childPosition];
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
// TODO inflate layout from xml instead
convertView = new TextView(parent.getContext());
}
// TODO use ViewHolder pattern instead
TextView textView = (TextView) convertView;
textView.setTypeface(null, Typeface.BOLD);
int childPosition = getGroup(groupPosition);
if (childPosition < 0) {
textView.setText("Choose an ingredient");
} else {
textView.setText(getChild(groupPosition, childPosition));
}
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
// TODO inflate layout from xml instead
convertView = new TextView(parent.getContext());
}
// TODO use ViewHolder pattern instead
TextView textView = (TextView) convertView;
textView.setText(getChild(groupPosition, childPosition));
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
public void selectChild(int groupPosition, int childPosition) {
mChoice[groupPosition] = childPosition;
}
@Override
public long getGroupId(int groupPosition) { return 0; }
@Override
public long getChildId(int groupPosition, int childPosition) { return 0; }
@Override
public boolean hasStableIds() { return false; }
}
正如 beworker 提到的,您的问题来自使用错误的数据结构,这就是您的应用程序崩溃的原因。您正在使用 header 标题作为哈希映射的键,当您修改 listDataHeader
中的标题时,修改会正确应用于它,但不适用于哈希映射内的键 object。这意味着您的 children 仍然存在于哈希图中的旧标题键下,而新标题键的值是 null
。因此,当您调用
NullPointerException
this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
因为
this.listDataChild.get(this.listDataHeader.get(groupPosition))
returns Null
解决方案是对 header 个标题使用 ArrayList,对 children 使用 ArrayList>。这两个 arrayLists 中的键是您的组索引。