点击按钮在Base Adapter中添加ListView项无响应问题求助
问题排查:ListView点击新增项失效+数组越界异常
我正尝试实现点击按钮创建新ListView项的功能,但存在未知Bug。多次重写代码、调用notifyDataSetChanged()均无效果,修改后还出现ArrayIndexOutOfBoundsException(length=3 index=3)异常。以下是我的MainActivity.java和CustomeAdapter.java代码,请求排查解决:
MainActivity.java
public Button btn; private ListView lv; private CustomeAdapter customeAdapter; public ArrayList<EditModel> editModelArrayList; int populateListMaxNum =3; int listNumber = populateListMaxNum; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.listView); btn = (Button) findViewById(R.id.btn); editModelArrayList = populateList(); customeAdapter = new CustomeAdapter(this,editModelArrayList); lv.setAdapter(customeAdapter); /* TODO activate button */ btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { addToList(); Toast.makeText(getApplicationContext(), "button", Toast.LENGTH_LONG).show(); } }); } private ArrayList<EditModel> populateList(){ //this part works perfectly ArrayList<EditModel> list = new ArrayList<>(); for(int i = 0; i < populateListMaxNum; i++){ EditModel editModel = new EditModel(); //editModel.setEditTextValue(String.valueOf(i)); list.add(editModel); } return list; } /*TODO make it work = expand */ private void addToList(){ // this part doesn't work nor it doesn't fail EditModel editModel = new EditModel(); editModelArrayList.add(editModel); customeAdapter.notifyDataSetChanged(); } }
CustomeAdapter.java
public class CustomeAdapter extends BaseAdapter { private Context context; public static ArrayList<EditModel> editModelArrayList; public CustomeAdapter(Context context, ArrayList<EditModel> editModelArrayList) { this.context = context; CustomeAdapter.editModelArrayList = editModelArrayList; } @Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; } @Override public int getCount() { return editModelArrayList.size(); } @Override public Object getItem(int position) { return editModelArrayList.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.lv_item, null, true); holder.editText = convertView.findViewById(R.id.editid); convertView.setTag(holder); }else { // the getTag returns the viewHolder object set as a tag to the view holder = (ViewHolder)convertView.getTag(); } holder.editText.setText(editModelArrayList.get(position).getEditTextValue()); holder.editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { editModelArrayList.get(position).setEditTextValue(holder.editText.getText().toString()); } @Override public void afterTextChanged(Editable editable) { } }); return convertView; } private class ViewHolder { protected EditText editText; } }
问题分析与修复方案
嘿,我帮你找到了几个导致问题的核心原因,改完就能正常工作了:
1. 视图类型配置错误(引发数组越界+更新失效)
你在CustomeAdapter里重写的getViewTypeCount()和getItemViewType()完全搞错了逻辑:
getViewTypeCount()返回getCount()意味着每个列表项都被当成一种独立的视图类型,ListView的视图复用机制直接失效。当你新增第4个项时,系统的视图缓存池大小还是初始的3,就会抛出ArrayIndexOutOfBoundsException。- 因为你的所有列表项布局都是一样的(都是
lv_item),所以正确的做法是:getViewTypeCount()返回1(表示只有一种视图类型)getItemViewType()返回0(所有项都属于这一种类型)- 甚至可以直接删掉这两个方法的重写,因为BaseAdapter默认的实现就是返回1和0,完全满足你的需求。
2. 静态ArrayList导致的潜在引用问题
你把Adapter里的editModelArrayList定义成了public static,这会导致如果后续创建多个Adapter实例,它们会共享同一个列表,很容易引发数据混乱。改成非静态的成员变量就好,直接用构造方法传入的列表引用。
3. 新增项的小优化(可选)
你的addToList()方法里新增的EditModel没有设置初始值,虽然不影响新增,但EditText会显示为空。如果想和初始化列表的逻辑保持一致,可以给新增的项设置默认值,比如editModel.setEditTextValue(String.valueOf(listNumber++))。
修改后的关键代码片段
修改后的CustomeAdapter
public class CustomeAdapter extends BaseAdapter { private Context context; private ArrayList<EditModel> editModelArrayList; // 去掉static修饰符 public CustomeAdapter(Context context, ArrayList<EditModel> editModelArrayList) { this.context = context; this.editModelArrayList = editModelArrayList; // 用成员变量存储,而非静态变量 } // 删掉错误的getViewTypeCount和getItemViewType,或者改成下面的正确实现 @Override public int getViewTypeCount() { return 1; } @Override public int getItemViewType(int position) { return 0; } // 其他方法保持不变,注意getItem里的引用是this.editModelArrayList(其实原来的也能跑,但规范一点) }
修改后的MainActivity的addToList方法
private void addToList(){ EditModel editModel = new EditModel(); editModel.setEditTextValue(String.valueOf(listNumber++)); // 新增初始值,可选 editModelArrayList.add(editModel); customeAdapter.notifyDataSetChanged(); }
改完这些之后,点击按钮就能正常新增ListView项了,数组越界的问题也会消失。核心问题就是错误的视图类型配置破坏了ListView的复用机制,导致界面不更新和异常抛出。
内容的提问来源于stack exchange,提问作者Atingas
相关产品推荐
相关产品推荐

