【问题标题】:NullPointerException at ExpandableListAdapter.getChild()ExpandableListAdapter.getChild() 处出现 NullPointerException
【发布时间】:2017-10-23 17:14:25
【问题描述】:

卡在这里一个多星期了,还是解决不了!我有一个expandable listView,其中数据是从SQLite 检索并设置为expListAdapter。单击箭头后,它将显示两个子项。

AddMonthlyExpenses

public class AddMonthlyExpenses extends AppCompatActivity {

    ArrayList<ListObj> groupList= new ArrayList<ListObj>();;
    List<String> childList;
    Map<ListObj, List<String>> laptopCollection;
    ExpandableListView listview;
    ExpandableListAdapter expListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_monthly_expenses);
        laptopCollection = new LinkedHashMap<ListObj, List<String>>();
        listview = (ExpandableListView) findViewById(R.id.exlistView);
        expListAdapter = new ExpandableListAdapter(getApplication(), groupList, laptopCollection);
        listview.setAdapter(expListAdapter);
        retrieveList(name);
    }

 public void retrieveList(String name) {
        database = mdb.getReadableDatabase();
        Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE__TASK + " WHERE Name = ? ", new String[]{name}, null);
        if (cursor != null && cursor.getCount() > 0) {
            while (cursor.moveToNext()) {
                groupList = new ArrayList<ListObj>();
                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    createCollection();  // for child items
                    listview.setAdapter(expListAdapter);
                }
            }
        }
    }

 private void createCollection() {
        String[] options = {"Edit","Delete"};
        for (ListObj laptop : groupList) {
            loadChild(options);
            laptopCollection.put(laptop, childList);
        }
    }

    private void loadChild(String[] laptopModels) {
        childList = new ArrayList<String>();
        for (String model : laptopModels)
            childList.add(model);
    }
}

ExpandableListAdapter

  public class ExpandableListAdapter extends BaseExpandableListAdapter {

    private Context context;
    Map<ListObj, List<String>> laptopCollections;
    private ArrayList<ListObj> laptops;
    double used = 0;
    private LayoutInflater mInflater;

    public ExpandableListAdapter(Context context, ArrayList<ListObj> laptops, Map<ListObj, List<String>> laptopCollections) {
        this.context = context;
        this.laptopCollections = laptopCollections;
        this.laptops = laptops;
        mInflater = LayoutInflater.from(context);
    }

    public Object getChild(int groupPosition, int childPosition) {  // error line
        if (laptopCollections.get(laptops.get(groupPosition)).get(childPosition) != null && !laptopCollections.get(laptops.get(groupPosition)).get(childPosition).isEmpty()) {
            return laptopCollections.get(laptops.get(groupPosition)).get(childPosition);
        }
        return 1;
    }

    public void add(int id, String month, double budget) {
        String[] splited = month.split("\\s+");
        ListObj obj = new ListObj(id, month, budget);
        obj.setYear(splited[1]);
        obj.setMonth(splited[0]);
        obj.setBudget(budget);
        obj.setID(id);
        laptops.add(obj);
        this.notifyDataSetChanged();
    }

    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

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

    public ListObj getItem(int position) {
        return laptops.get(position);
    }

    public View getChildView(final int groupPosition, final int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final String laptop = (String) getChild(groupPosition, childPosition);   // here the error line 
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.child_item, null);
        }
        TextView edit = (TextView) convertView.findViewById(R.id.textEdit);
        edit.setText(laptop);
        return convertView;
    }

    public int getChildrenCount(int groupPosition) {
        if (laptopCollections.get(laptops.get(groupPosition)) != null && !  laptopCollections.get(laptops.get(groupPosition)).isEmpty()) {
            return  laptopCollections.get(laptops.get(groupPosition)).size();
        }
        return 1;
    }

    public Object getGroup(int groupPosition) {
        return laptops.get(groupPosition);
    }

    public int getGroupCount() {
        return this.laptops.size();
    }

    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        ExpensesAdapter.ViewHolder holder = null;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.expenses_adapter, null);
            holder = new ExpensesAdapter.ViewHolder();
            holder.month = (TextView) convertView.findViewById(R.id.textMonth);
            holder.budget = (TextView) convertView.findViewById(R.id.textAmount);
            holder.year = (TextView) convertView.findViewById(R.id.textYear);
            convertView.setTag(holder);
        } else {
            holder = (ExpensesAdapter.ViewHolder) convertView.getTag();
        }
        holder.month.setText(laptops.get(groupPosition).getMonth());
        holder.budget.setText(String.format("%.2f", laptops.get(groupPosition).getBudget()));
        holder.year.setText(laptops.get(groupPosition).getYear());
        return convertView;
    }

    public boolean hasStableIds() {
        return true;
    }

    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

错误

10-26 00:03:57.114 23612-23612/com.example.tony.monthlyexpenses E/AndroidRuntime: 致命异常: main java.lang.NullPointerException 在 com.example.tony.monthlyexpenses.adapter.ExpandableListAdapter.getChild(ExpandableListAdapter.java:42) 在 com.example.tony.monthlyexpenses.adapter.ExpandableListAdapter.getChildView(ExpandableListAdapter.java:87) 在 android.widget.ExpandableListConnector.getView(ExpandableListConnector.java:451) 在 android.widget.AbsListView.obtainView(AbsListView.java:2232) 在 android.widget.ListView.makeAndAddView(ListView.java:1849) 在 android.widget.ListView.fillDown(ListView.java:678) 在 android.widget.ListView.fillSpecific(ListView.java:1339)

我的应用程序屏幕截图

我尝试调试但没有任何内容为空!

你可以从下面的链接克隆我的项目

https://github.com/wseng92/MonthlyExpenses

【问题讨论】:

  • if (laptopCollections.get(laptops.get(groupPosition)).get(childPosition) != null &amp;&amp; !laptopCollections.get(laptops.get(groupPosition)).get(childPosition).isEmpty())这一行放一个断点。并检查其中是否有任何内容为空
  • 你能在 github 上发布一个具有这种行为的简单项目吗?
  • 你必须了解什么是 NullPointerException,当变量为 null 并在其上调用方法时会引发此异常。因此,您的错误来自以下其中一项为空:laptopCollections、laptops、get(laptops.get(groupPosition)) 等。您可以将支票更改为以下内容:if(laptopCollections != null &amp;&amp; laptops != null &amp;&amp; laptopCollections.get(laptops.get(groupPosition)) != null &amp;&amp; laptopCollections.get(laptops.get(groupPosition)).get(child‌​Position) != null &amp;&amp; ...)。另一个思路是使用Stream Api,使用filter方法进行优化。
  • @azizbekian 你可以从github.com/wseng92/MonthlyExpenses克隆我的项目

标签: java android nullpointerexception expandablelistview android-adapter


【解决方案1】:

添加 createCollection();到 button1 setonclick 监听器

createCollection();

groupList = new ArrayList();写在for循环里面可能有问题?它为每个循环创建一个新的数组列表,因此您的数组大小始终为 1(最后一次迭代计数)

while (cursor.moveToNext()) {
                groupList = new ArrayList<ListObj>();
                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                createCollection();  // for child items
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    listview.setAdapter(expListAdapter);
                }
            }

改成

groupList = new ArrayList<ListObj>();
while (cursor.moveToNext()) {

                int iD = cursor.getInt(cursor.getColumnIndex("ID"));
                String month = cursor.getString(cursor.getColumnIndex("Month"));
                double budget = cursor.getDouble(cursor.getColumnIndex("Budget"));
                groupList.add(new ListObj(iD,month,budget));
                createCollection();  // for child items
                if (expListAdapter != null) {
                    expListAdapter.add(iD, month, budget);
                    listview.setAdapter(expListAdapter);
                }
            }

【讨论】:

  • 试过但没有成功
  • 在 for 循环中是否需要再次设置适配器?我认为不是多个 setAdapter 调用.. 只是在循环完成后调用 notifyDataSetChanged?
  • 你的意思是删除 setAdapter ?
  • 是的,不需要第二个 setAdapter .. 填充列表视图后通知数据集已更改
  • 我更改为listview.deferNotifyDataSetChanged();,但仍然出现同样的错误
【解决方案2】:

我在一两年前遇到了类似的问题。不记得是哪个版本了。

从通话开始

public Object getChild(int groupPosition, int childPosition) {
   if (laptopCollections.get(laptops.get(groupPosition)).get(childPosition) ...

笔记本电脑的价值是什么?用构造函数初始化

public ExpandableListAdapter(Context context, ArrayList<ListObj> laptops ...

第二个参数,创建于AddMonthlyExpenses.onCreate()

expListAdapter =
   new ExpandableListAdapter(getApplication(), groupList, laptopCollection);

并在声明中初始化

 ArrayList<ListObj> groupList= new ArrayList<ListObj>();;

出于某种我不知道的原因 - Android 特性 - 在我的情况下,这个 groupList(或我拥有的类似成员字段)是 NULL,即使它是在声明时初始化的。

但是将初始化移动到onCreate() 中解决了这个问题。

试试看。或者至少调试引用laptops的行。

【讨论】:

    【解决方案3】:

    我认为在你的代码中不起作用

    laptopCollections.get(laptops.get(groupPosition)).size();

    因为尝试查找其他对象实例。

    你的片段和适配器中有这么多列表,你真的不需要这个。尝试保持 OOP 并对其进行重构并为此创建更好的模型。

    或者更简单的方法不用于映射键对象,而是用于 id。

    Map&lt;ListObj, List&lt;String&gt;&gt; laptopCollectionsMap&lt;String,List&lt;String&gt;&gt; laptopCollections 其中第一个 K 是 id。 也许会有所帮助。

    【讨论】:

    • 但我需要使用 Obj (ListObj) 而不是 String,因为数据是从 SQLite 检索的
    • 你真的不需要从 ListObj 中使用只有 id 像 key .... map 然后只使用 id 在地图中查找因为当你使用 ListObj 时你保存到地图键例如ListObj@1253 然后用于查找 ListObj@2569 它的两个不同实例。尝试调试您的代码,此代码 notebookCollections.get(laptops.get(groupPosition)) return null
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多