【问题标题】:java.lang.NullPointerException when try listview.getChildAt()尝试 listview.getChildAt() 时出现 java.lang.NullPointerException
【发布时间】:2014-10-22 12:33:33
【问题描述】:

存在具有正确值的 ListView:

public class FragmentTab1 extends SherlockFragment {

ListView list;
LazyAdapter adapter;

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    list = (ListView) getActivity().findViewById(android.R.id.list); //also I tried view.findViewById(android.R.id.list)
    ............

    adapter = new LazyAdapter(getActivity(), mSource);
    list.setAdapter(adapter);
} 
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
    View rootView = inflater.inflate(R.layout.fragmenttab1, container, false);
    return rootView;

}

当我尝试时:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId(); //correct
    int itemCount = list.getCount();  // 10 ps as show Logcat
    if (R.id.save == id) {
        CheckBox cb;
        for(int i = itemCount - 1; i >= 0; i--) {
            cb = (CheckBox)list.getChildAt(i).findViewById(R.id.checkBox1);  //Error here
        }
    }
    return true;
}

xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<CheckBox
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Save to database"
    android:id="@+id/checkBox1" />  // same id

接下来是适配器:

public class LazyAdapter extends BaseAdapter {

private Activity activity;
ArrayList<Bitmap> bitmapArray = new ArrayList<Bitmap>();
private ArrayList<Data> mObjects;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;

public LazyAdapter(Activity a, ArrayList<Data> mObjects1) {
    activity = a;
    mObjects = mObjects1;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    imageLoader=new ImageLoader(activity.getApplicationContext());
}

public int getCount() {
    return mObjects.size();
}

public Object getItem(int position) {
    return position;
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    Data item = mObjects.get(position);
    View vi=convertView;
    if(convertView==null)
        vi = inflater.inflate(R.layout.item_internet, null);
    TextView text=(TextView)vi.findViewById(R.id.title1);
    ImageView image=(ImageView)vi.findViewById(android.R.id.icon);
    text.setText(item.getmTitle());
    bitmapArray.add(imageLoader.getBitmap());
    imageLoader.DisplayImage(item.getmImageUrl(), image);
    return vi;
}

我收到正确的 ListView,但是当我尝试单击操作栏中的保存按钮时收到错误消息。 可能,我应该在适配器中初始化 CheckBox 吗? 有人可以帮助我吗?

【问题讨论】:

标签: java android listview menuitem


【解决方案1】:

如果子项不可见,list.getChildAt(i) 将为 null。所以在使用前检查null。

因此您无法以这种方式检索所有选中的项目。

请发布完整的.xml 和&lt;Data&gt; 的定义。

【讨论】:

    【解决方案2】:

    我认为你会得到一个 indexoutofbounds 但由于它为空,这可能就是原因:ListView getChildAt returning null for visible children

    另外,在你的 for 循环中放一条日志语句来显示所有相关变量的值,例如:i 和 itemCount 等。

    并在循环之前设置一个断点并运行调试模式以在循环通过时检查值,您将看到 i 值导致调试器中的空指针,或者如果您错过它,它将在日志猫

    【讨论】:

      【解决方案3】:

      我知道这是很老的帖子。但我正在回答,因为人们仍在寻找解决 ListView getChildAt() 空指针异常的方法。

      这是因为 ArrayApdater 正在移除和回收由于高度而在 ListView 上尚不可见的视图。因此,如果您有 10 个项目视图,并且 ListView 一次可以显示 4 - 5 个:

      • Adapter REMOVE 位置 5 到 9 的 item 视图,这样任何对adapter.getChildAt(5... to 9) 的尝试都会导致空指针异常

      • 适配器还会回收项目视图,因此当您向下滚动到 5 到 9 时,您在位置 3 上所做的任何引用都会丢失,您在位置 3 上所做的任何输入(EditText、复选框等)将在您向下滚动到 5 到 9 时被回收,稍后将在另一个位置(例如位置 1、2 或 3 等)以相同的值重复使用

      我发现控制它的唯一方法是忘记获取视图并拥有:

      • 属性HashMap&lt;Integer, Boolean&gt; cbValues 或您想要用于处理列表中每个项目的值的任何类型。对于item-&gt;getId()position 等项目,第一种类型必须是唯一的。在构造函数中使用新的HashMap&lt;&gt;() 对其进行初始化;
      • 为输入视图添加 InputListener,(addTextChangedListener 用于 EditText,setOnCheckedChangeListener 用于 Checkbox 等)并在输入时更新 HashMap 键(item.getId()position)和值(editable.toString() 或 @ 987654331@ 或 false)。前任。在@Override public void onCheckedChanged 上,输入布尔结果cbValues.put(item.getId(), b);
      • 防止适配器使用回收的convertView,删除条件if(convertView == null),以便适配器总是膨胀一个全新的视图实例。因为视图实例每次都是新的,所以每次都必须从 HashMap 中设置值,就像它已经包含键 if(cbValues.containsKey(item.getId())){cbItem.setChecked(cbValue.get(cbItem.getId()))}; 一样。在这种情况下,可能没有大量的项目,因此平滑滚动不是必须的。

      • 最后创建公共方法来获取适配器之外的值,将item-&gt;getId()整数作为参数传递。例如:'public bool getCheckboxValueForItemId(int itemId) { return cbValues.get(itemId); }`。然后很容易从适配器中选择项目

      这是最后的代码:

      public class LazyAdapter extends BaseAdapter {
      
      
      private Activity activity;
      ArrayList<Bitmap> bitmapArray = new ArrayList<Bitmap>();
      private ArrayList<Data> mObjects;
      private static LayoutInflater inflater=null;
      public ImageLoader imageLoader;
      
      HashMap<Integer, Boolean> cbValues;
      
      public LazyAdapter(Activity a, ArrayList<Data> mObjects1) {
          activity = a;
          mObjects = mObjects1;
          cbValues = new HashMap<>();
          inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          imageLoader=new ImageLoader(activity.getApplicationContext());
      }
      
      public int getCount() {
          return mObjects.size();
      }
      
      public Object getItem(int position) {
          return position;
      }
      
      public long getItemId(int position) {
          return position;
      }
      
      public View getView(int position, View convertView, ViewGroup parent) {
          Data item = mObjects.get(position);
          View vi=convertView;
          // Remove convertView condition
          //if(convertView==null)
      
          vi = inflater.inflate(R.layout.item_internet, null);
          TextView text=(TextView)vi.findViewById(R.id.title1);
          ImageView image=(ImageView)vi.findViewById(android.R.id.icon);
          Checkbox cbItem = (Checkbox) vi.findViewById(android.R.id.checkbox1);
          text.setText(item.getmTitle());
          bitmapArray.add(imageLoader.getBitmap());
          imageLoader.DisplayImage(item.getmImageUrl(), image);
      
          if(cbValues.containsKey(item.getId())) {
              cbItem.setChecked(cbValue.get(cbItem.getId()))};
          }
      
          cbItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
              @Override
              public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                 cbValues.put(item.getId(), b);
             }
          });
      
          return vi;
      }
      
      // itemId : unique identifier for an Item, not the position of Item in Adapter
      public bool getCheckboxValueForItemId(int itemId) {
          return cbValues.get(itemId);
      }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2018-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-05
        • 1970-01-01
        • 1970-01-01
        • 2014-08-26
        • 2014-10-22
        相关资源
        最近更新 更多