GridView加载超10张MySQL图片时点击Continue触发空指针异常求助
问题根源
你遇到的java.lang.NullPointerException本质原因是:GridView只会实例化当前屏幕可见的子View。当图片数量超过10张(超出屏幕显示范围)时,那些不在视野内的item并没有被加载到内存中,调用gridView.getChildAt(i)会返回null,这时候再调用linearLayout.findViewById()自然就触发空指针了。
另外,你原代码还有个隐藏问题:在遍历选中项的循环里,每次发现选中项就直接跳转Activity了,这会导致只收集到第一个选中项就跳走,根本没机会收集其他选中内容。
修复方案
正确的做法是依赖数据源维护选中状态,而不是直接操作GridView的子View。你已经在ImageAdapter的OnCheckedChangeListener里通过images.get(getPosition).setSelected(buttonView.isChecked())维护了每个item的选中状态,直接从这个数据源里读取选中项即可。
1. 修正Continue按钮的点击事件代码
把原来通过gridView.getChildAt(i)获取View的逻辑,改成直接遍历你的images数据源:
proceed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ArrayList<String> selectedItems = new ArrayList<String>(); // 遍历数据源,直接读取选中状态 for(int i = 0; i < images.size(); i++) { ImagesLib currentImage = images.get(i); if(currentImage.isSelected()){ // 这里根据你的需求添加对应数据,比如图片ID selectedItems.add(currentImage.getId()); Log.d("Selected Item: " + i, currentImage.getId()); } } // 收集完所有选中项后,再跳转页面 String[] strArr = selectedItems.toArray(new String[0]); Intent intent = new Intent(getApplicationContext(), ResultActivity.class); Bundle b = new Bundle(); b.putStringArray("selectedItems", strArr); intent.putExtras(b); startActivity(intent); finish(); } });
2. 修复Adapter中重复设置Tag的问题
你在ImageAdapter的getView里给CheckBox设置了两次Tag,后一次会覆盖前一次:
// 原代码:两次setTag会覆盖 viewHolder.Chkbox.setTag(image.getId()); viewHolder.Chkbox.setTag(position);
改用带key的setTag(int key, Object tag)来区分不同的Tag(需要先在res/values/ids.xml里定义两个key,或者用系统已有的id,自定义更清晰):
// 存储图片ID viewHolder.Chkbox.setTag(R.id.tag_image_id, image.getId()); // 存储位置索引 viewHolder.Chkbox.setTag(R.id.tag_position, position);
然后在OnCheckedChangeListener里获取位置:
int getPosition = (Integer) buttonView.getTag(R.id.tag_position); images.get(getPosition).setSelected(buttonView.isChecked());
为什么这样有效?
这种方式遵循了Android Adapter的设计思想:数据源是唯一的真相来源,View只是数据源的可视化展示。不管GridView有多少item,只要数据源里的选中状态是正确的,就能准确收集所有选中项,完全不会因为View未加载而出现空指针问题。
内容的提问来源于stack exchange,提问作者prince vincy

