Java 从SQL数据库中删除条目后出现Nullpointer异常

Java 从SQL数据库中删除条目后出现Nullpointer异常,java,android,database,android-studio,Java,Android,Database,Android Studio,我正在为一个机器人开发一个应用程序,在这个应用程序中,用户可以定义机器人稍后将从设备获取的穿孔组合。为了允许用户存储这些培训,我定义了一个类“trainings”,其中包含培训的id、名称和打孔组合。此培训稍后保存在一个数据库中,为此我编写了一个DatabaseHandler类。添加和显示数据工作正常,但每当我想使用以下方法删除条目时: public void deleteTraining(Training training) { SQLiteDatabase db = th

我正在为一个机器人开发一个应用程序,在这个应用程序中,用户可以定义机器人稍后将从设备获取的穿孔组合。为了允许用户存储这些培训,我定义了一个类“trainings”,其中包含培训的id、名称和打孔组合。此培训稍后保存在一个数据库中,为此我编写了一个DatabaseHandler类。添加和显示数据工作正常,但每当我想使用以下方法删除条目时:

    public void deleteTraining(Training training) {
      SQLiteDatabase db = this.getWritableDatabase();

      db.delete(TABLE_TRAININGS, KEY_ID + " = ?",
      new String[] { String.valueOf(training.getID()) });
      db.close();
}
然后再次尝试填充我的GridView(由GridAdapter类处理),我会得到一个Nullpointer异常

java.lang.NullPointerException:尝试读取空对象引用上的字段“java.lang.String com.noeth.tobi.McRobektrainingPlaner.Training.\u name”
在com.noeth.tobi.mcrobektrainingsplaner.GridAdapter.getView(GridAdapter.java:50)

GridAdapter的getView方法:

public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        // if it's not recycled, initialize some attributes
        btn = new Button(context);
        btn.setLayoutParams(new GridView.LayoutParams(370, 350));
        btn.setPadding(2,100,2,100);
        btn.setOnClickListener(new CustomOnClickListener(position, context));
        btn.setOnLongClickListener(new CustomOnLongClickListener(position, context, btn));

    }
    else {
        btn = (Button) convertView;
    }

    btn.setText(db.getTraining(position)._name); //Here the programm throws a Nullpointer Exception AFTER deleting an entry from the database

    btn.setTextColor(Color.WHITE);
    btn.setBackgroundResource(R.drawable.button_border);
    btn.setTag("not_activated");
    btn.setId(position);

    return btn;
}
我认为这一定与已删除培训的id有关,因为循环只是遍历所有id,所以我编写了一个方法recalcIDs,它重新计算已删除培训后的每个项目的id:
反抗者


我假设
Training.setId
方法不调用数据库。 您不应该更改培训的id,因为它们由参考底图数据库管理。如果只更改应用程序逻辑中的ID,则两个数据集(应用程序和数据库)将有所不同。
我建议在用户决定删除一个培训后重新加载数据库中的所有培训,然后调用
Gridview.notifyDatasetChanged

首先从数据库中查询所有有效的ID,然后将它们映射到位置。这是否意味着数据库本身对每个项目都有一个唯一的ID?现在,
DatabaseHandler.getTraining
调用并由
Training.setID
设置的ID是培训类中的一个变量。很抱歉提出这样的问题,但我不经常使用数据库。还有一个问题:您如何确定已经插入了多少培训?所以我可能会问您一个问题:作为快速解决方案,您应该从培训计数中减去一,在gridview上调用notifydatasetchanged并在getView中检查来自数据库的培训是否为null。如果为空,您可以返回一个不可见的视图。否则,只需像以前一样使用适配器。对于这个问题有一个更干净的解决方案:通过一个sql调用获取当前的数据库培训列表。请查看这篇关于如何实现这个()的文章。谢谢,看起来很有希望,我会尽快测试它。如果有帮助,我会接受你的答案。
public void recalcIDs(){
    int k = 1;
    int subtract = 1;
    int id;
    Training training;

    for(int i = deleted.get(0)+1; i < db.getTrainingCount(); i++){
        if(deleted.size() > 1){
            if(i < deleted.get(k)){
                training = db.getTraining(i);
                id = training.getID();
                training.setID(id-subtract);
            }
            else{
                k+=1;
                subtract+=1;
            }
        }
        else{
            training = db.getTraining(i);
            id = training.getID();
            training.setID(id-subtract);
        }


    }

} 
Training getTraining(int id) {
    SQLiteDatabase db = this.getReadableDatabase();
    Training training;
    Cursor cursor = db.query(TABLE_TRAININGS, new String[] { KEY_ID,
                    KEY_NAME, KEY_SK}, KEY_ID + "=?",
            new String[] { String.valueOf(id) }, null, null, null, null);
    if (cursor != null && cursor.moveToFirst()){

     training = new Training(Integer.parseInt(cursor.getString(0)),
            cursor.getString(1), cursor.getLong(2));
        cursor.close();
    }
    else{
        training = null;
        Toast.makeText(con,"Couldn't find any training sessions!", Toast.LENGTH_LONG).show();
    }

    // return training
    return training;
}