-1

Why I'am asking: I don't want to sound rude, but I'am very desperate. I tried the things, you have described in several questions for about 8 hours, but I don't get it without help from somebody else. I understand the theory of NullPointerExceptions and your examples, but I don't know how to do it better especially in comparison to an example, which works well. I modify only a few variables for my table in database and I need some explanations regarding my case. I would not ask, if I can find the answer on my own. Please help me with my issue.

I try to learn Android Programming. In order to do that I worked with a tutorial which explains how to create a SQLite database.

Although I checked my code with the one of the author and checked Stack Overflow regarding this error, I have not found my mistake yet.

When I test my application, there is following in my Logcat:

    02-25 14:00:48.951 16343-16343/de.der_kalorienzaehler.kalorienzaehler D/AndroidRuntime: Shutting down VM
    02-25 14:00:49.007 16343-16343/de.der_kalorienzaehler.kalorienzaehler E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                                Process: de.der_kalorienzaehler.kalorienzaehler, PID: 16343
                                                                                                java.lang.RuntimeException: Unable to start activity ComponentInfo{de.der_kalorienzaehler.kalorienzaehler/de.der_kalorienzaehler.kalorienzaehler.zutat_bearbeiten}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor 
...                                                                                              
                                                                                                 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String)' on a null object reference
                                                                                                    at de.der_kalorienzaehler.kalorienzaehler.DbZugriff.getAllGrundgeruestZutatenverwaltung(DbZugriff.java:92)
                                                                                                    at de.der_kalorienzaehler.kalorienzaehler.zutat_bearbeiten.listenEintraegeZeigen(zutat_bearbeiten.java:58)
                                                                                                    at de.der_kalorienzaehler.kalorienzaehler.zutat_bearbeiten.onCreate(zutat_bearbeiten.java:49)

I think the line which caused all my problems ist following: de.der_kalorienzaehler.kalorienzaehler.DbZugriff.getAllGrundgeruestZutatenverwaltung(DbZugriff.java:92)

The other problems which are in the Activity "zutat_bearbeiten" relying on the value of the cursor, so they needn't to be changed. I tried to initialise db as suggested in other posts in my class called "dbErzeugenUpdaten". But when I tried, there was either an infinite loop or I can't initialise it because it's already there.

So my question is, what do I have to write in order to avoid the NullPointerException? Maybe I am wrong with the root of my problem, so I show you the class "zutat_bearbeiten" as well, but this class should be okay, if the problem with the Cursor is solved?

I'm looking forward to your help.

DbZugriff class:

package de.der_kalorienzaehler.kalorienzaehler;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.content.ContentValues;
import android.database.Cursor;
import java.util.ArrayList;
import java.util.List;
public class DbZugriff {

    private static final String LOG_TAG = DbZugriff.class.getSimpleName();

    private SQLiteDatabase database;
    private DbErzeugenUpdaten dbErzeugenUpdaten;

    //Für Suchanfragen
    private String[] columns = {
            DbErzeugenUpdaten.COLUMN_ID,
            DbErzeugenUpdaten.COLUMN_ZUTAT,
            DbErzeugenUpdaten.COLUMN_ANZAHL,
            DbErzeugenUpdaten.COLUMN_EINHEIT,
            DbErzeugenUpdaten.COLUMN_KCAL
    };

    //Context: Zugang zu Android Funktionen
    public DbZugriff(Context DbZugriff) {
        Log.d(LOG_TAG, "Unsere DataSource erzeugt jetzt den DbErzeugenUpdaten.");
        dbErzeugenUpdaten = new DbErzeugenUpdaten(DbZugriff);
    }

    public void open(){
        Log.d(LOG_TAG, "Eine Referenz auf die Datenbank wird angefragt");
        database = dbErzeugenUpdaten.getWritableDatabase();
        Log.d(LOG_TAG, "Datenbankreferenz erhalten. Pfad zur Datenbank" + database.getPath());
    }

    public void close(){
        dbErzeugenUpdaten.close();
        Log.d(LOG_TAG, "Datenbank mithilfe der Methode DbErzeugenUpdaten geschlossen");
    }

    //Einfügen von Daten in db
    public GrundgeruestZutatenverwaltung createGrundgeruestZutatenverwaltung(
            String zutat, double anzahl, String einheit, int kcal) {
        ContentValues daten_zutat = new ContentValues();
        daten_zutat.put(DbErzeugenUpdaten.COLUMN_ZUTAT, zutat);
        daten_zutat.put(DbErzeugenUpdaten.COLUMN_ANZAHL, anzahl);
        daten_zutat.put(DbErzeugenUpdaten.COLUMN_EINHEIT, einheit);
        daten_zutat.put(DbErzeugenUpdaten.COLUMN_KCAL, kcal);

        //nach id die Daten einfügen
        long idEinfuegen = database.insert(DbErzeugenUpdaten.TABLE_ZUTATENLISTE, null, daten_zutat);

        Cursor cursor = database.query(DbErzeugenUpdaten.TABLE_ZUTATENLISTE, columns,
                DbErzeugenUpdaten.COLUMN_ID + "=" + idEinfuegen, null, null, null, null);
        cursor.moveToFirst();
        GrundgeruestZutatenverwaltung datenCursor = cursorToGrundgeruestZutatenverwaltung(cursor);
        cursor.close();

        return datenCursor;
    }

    //Auslesen von Daten, aus Cursordaten werden Daten zur Weiterverwendung
    private GrundgeruestZutatenverwaltung cursorToGrundgeruestZutatenverwaltung(Cursor cursor){
        int idIndex = cursor.getColumnIndex(DbErzeugenUpdaten.COLUMN_ID);
        int idZutat = cursor.getColumnIndex(DbErzeugenUpdaten.COLUMN_ZUTAT);
        int idAnzahl = cursor.getColumnIndex(DbErzeugenUpdaten.COLUMN_ANZAHL);
        int idEinheit = cursor.getColumnIndex(DbErzeugenUpdaten.COLUMN_EINHEIT);
        int idKcal = cursor.getColumnIndex(DbErzeugenUpdaten.COLUMN_KCAL);

        long id = cursor.getLong(idIndex);
        String zutat = cursor.getString(idZutat);
        double anzahl = cursor.getDouble(idAnzahl);
        String einheit = cursor.getString(idEinheit);
        int kcal = cursor.getInt(idKcal);


        GrundgeruestZutatenverwaltung datenCursor = new GrundgeruestZutatenverwaltung
                (id, zutat, anzahl, einheit, kcal);
        return datenCursor;
    }

    //Auslesen aller Datensätze
    public List<GrundgeruestZutatenverwaltung> getAllGrundgeruestZutatenverwaltung(){
        List<GrundgeruestZutatenverwaltung> zutatenListe = new ArrayList<>();

        //Nullpointer Exception -> das ist einer der wichtigeren Probleme
        Cursor cursor = database.query(DbErzeugenUpdaten.TABLE_ZUTATENLISTE, columns,
                null, null, null, null, null);

        cursor.moveToFirst();
        GrundgeruestZutatenverwaltung datenCursor;

        //Zeilenweise auslesen der Tabelle und werden zu umgewandelte Objekte, die in die zutatenListe kommen
        while (!cursor.isAfterLast()){
            datenCursor = cursorToGrundgeruestZutatenverwaltung(cursor);
            zutatenListe.add(datenCursor);
            Log.d(LOG_TAG, "ID:" + datenCursor.getId() + ", Inhalt:"
            + datenCursor.toString());
            cursor.moveToNext();
        }
        cursor.close();
        return zutatenListe;
    }


}

I made my class by modifying this class (it worked well, when I try it):

package de.programmierenlernenhq.shoppinglisthq;


import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import android.content.ContentValues;
import android.database.Cursor;
import java.util.ArrayList;
import java.util.List;


public class ShoppingMemoDataSource {

    private static final String LOG_TAG = ShoppingMemoDataSource.class.getSimpleName();

    private SQLiteDatabase database;
    private ShoppingMemoDbHelper dbHelper;

    private String[] columns = {
            ShoppingMemoDbHelper.COLUMN_ID,
            ShoppingMemoDbHelper.COLUMN_PRODUCT,
            ShoppingMemoDbHelper.COLUMN_QUANTITY
    };

    public ShoppingMemoDataSource(Context context) {
        Log.d(LOG_TAG, "Unsere DataSource erzeugt jetzt den dbHelper.");
        dbHelper = new ShoppingMemoDbHelper(context);
    }

    public void open() {
        Log.d(LOG_TAG, "Eine Referenz auf die Datenbank wird jetzt angefragt.");
        database = dbHelper.getWritableDatabase();
        Log.d(LOG_TAG, "Datenbank-Referenz erhalten. Pfad zur Datenbank: " + database.getPath());
    }

    public void close() {
        dbHelper.close();
        Log.d(LOG_TAG, "Datenbank mit Hilfe des DbHelpers geschlossen.");
    }

    public ShoppingMemo createShoppingMemo(String product, int quantity) {
        ContentValues values = new ContentValues();
        values.put(ShoppingMemoDbHelper.COLUMN_PRODUCT, product);
        values.put(ShoppingMemoDbHelper.COLUMN_QUANTITY, quantity);

        long insertId = database.insert(ShoppingMemoDbHelper.TABLE_SHOPPING_LIST, null, values);

        Cursor cursor = database.query(ShoppingMemoDbHelper.TABLE_SHOPPING_LIST,
                columns, ShoppingMemoDbHelper.COLUMN_ID + "=" + insertId,
                null, null, null, null);

        cursor.moveToFirst();
        ShoppingMemo shoppingMemo = cursorToShoppingMemo(cursor);
        cursor.close();

        return shoppingMemo;
    }

    private ShoppingMemo cursorToShoppingMemo(Cursor cursor) {
        int idIndex = cursor.getColumnIndex(ShoppingMemoDbHelper.COLUMN_ID);
        int idProduct = cursor.getColumnIndex(ShoppingMemoDbHelper.COLUMN_PRODUCT);
        int idQuantity = cursor.getColumnIndex(ShoppingMemoDbHelper.COLUMN_QUANTITY);

        String product = cursor.getString(idProduct);
        int quantity = cursor.getInt(idQuantity);
        long id = cursor.getLong(idIndex);

        ShoppingMemo shoppingMemo = new ShoppingMemo(product, quantity, id);

        return shoppingMemo;
    }

    public List<ShoppingMemo> getAllShoppingMemos() {
        List<ShoppingMemo> shoppingMemoList = new ArrayList<>();

        Cursor cursor = database.query(ShoppingMemoDbHelper.TABLE_SHOPPING_LIST,
                columns, null, null, null, null, null);

        cursor.moveToFirst();
        ShoppingMemo shoppingMemo;

        while(!cursor.isAfterLast()) {
            shoppingMemo = cursorToShoppingMemo(cursor);
            shoppingMemoList.add(shoppingMemo);
            Log.d(LOG_TAG, "ID: " + shoppingMemo.getId() + ", Inhalt: " + shoppingMemo.toString());
            cursor.moveToNext();
        }

        cursor.close();

        return shoppingMemoList;
    }
}

dbErzeugenUpdaten class:

//Tabelle wird erzeugt
package de.der_kalorienzaehler.kalorienzaehler;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DbErzeugenUpdaten extends SQLiteOpenHelper {
    //Methode getSimpleName gibt den Klassenname der Datei aus
    private static final String LOG_TAG =
            DbErzeugenUpdaten.class.getSimpleName();

    public static final String DB_NAME = "kcal_berechnen.db";
    public static final int DB_VERSION = 1;
    public static final String TABLE_ZUTATENLISTE = "zutatenliste";

    public static final String COLUMN_ID = "_id";
    public static final String COLUMN_ZUTAT = "zutat";
    public static final String COLUMN_ANZAHL = "anzahl";
    public static final String COLUMN_EINHEIT = "einheit";
    public static final String COLUMN_KCAL = "kcal";

    public static final String SQL_CREATE =
            "CREATE TABLE " + TABLE_ZUTATENLISTE +
            "(" + COLUMN_ID  + " INTEGER PRIMARY KEY AUTOINCREMENT , " +
                COLUMN_ZUTAT  + " TEXT NOT NULL, " +
                COLUMN_ANZAHL  + " FLOAT NOT NULL, " +
                COLUMN_EINHEIT  + " TEXT NOT NULL, " +
                COLUMN_KCAL  + " INTEGER NOT NULL);";

    //Konstruktor, neue Instanz, wichtigste Daten für Erzeugung der db, db_info enthält Daten
    public DbErzeugenUpdaten (Context db_info){
        super(db_info, DB_NAME, null, DB_VERSION);
        // Log.d sendet eine Debug Log Nachricht
        Log.d(LOG_TAG, "Datenbank " + getDatabaseName() + " erzeugt");


    }

    //wird nur aufgerufen, wenn die Datenbank nicht existiert
    @Override
    public void onCreate(SQLiteDatabase db) {
        // muss initialisiert werden

        if (db != null){
            Log.d(LOG_TAG, "db ist nicht null");
        }else{
            Log.d(LOG_TAG, "db ist null");
        }
        Log.d(LOG_TAG, "DbErzeugenUpdaten OnCreate wird aufgerufen");
        try{
            Log.d(LOG_TAG, "Tablle wurde mithilfe" + SQL_CREATE + "angelegt");
            db.execSQL(SQL_CREATE);
        }catch(Exception ex){
            Log.e(LOG_TAG, "Fehler beim Anlegen der Tabelle" + ex.getMessage());
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

zutat_bearbeiten class:

package de.der_kalorienzaehler.kalorienzaehler;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.List;

public class zutat_bearbeiten extends AppCompatActivity {

    public static final String LOG_TAG = hauptmenue.class.getSimpleName();
    private DbZugriff dbZugriff;

    //Schreiben in Datenbank
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zutat_bearbeiten);

        dbZugriff = new DbZugriff(this);

        GrundgeruestZutatenverwaltung datenCursor;

        Log.d(LOG_TAG, "Datenquelle wird geöffnet");
        dbZugriff.open();

        datenCursor = dbZugriff.createGrundgeruestZutatenverwaltung("Testprodukt", 2, "kg", 123);
        Log.d(LOG_TAG, "Es wurde der folgende Eintrag in die Datenbank geschrieben:");
        Log.d(LOG_TAG, "ID: " + datenCursor.getId() + ", Inhalt: " + datenCursor.toString());

        Log.d(LOG_TAG, "Folgende Einträge sind in der Datenbank vorhanden:");
        listenEintraegeZeigen();


        dbZugriff = new DbZugriff(this);

        Log.d(LOG_TAG, "Folgender Eintrag in Datenbank: ");
        Log.d(LOG_TAG, "ID" + datenCursor.getId()
                    +   "Zutat" + datenCursor.getZutat()
                    +   "Anzahl" + datenCursor.getAnzahl()
                    +   "Einheit" + datenCursor.getEinheit()
                    +   "Kcal" + datenCursor.getKcal());


        Log.d(LOG_TAG, "Folgende Einträge sind in der Datenbank vorhanden:");

        //Nullpointer Exception, kommt von Methode -> irrelevant
        listenEintraegeZeigen();

        Log.d(LOG_TAG, "Datenquelle wird geschlossen");
        dbZugriff.close();
    }

    private void listenEintraegeZeigen(){
        //Nullpointer Exception
        List<GrundgeruestZutatenverwaltung> zutatenListe =
                dbZugriff.getAllGrundgeruestZutatenverwaltung();

        ArrayAdapter<GrundgeruestZutatenverwaltung> zutatenverwaltungArrayAdapter =
                new ArrayAdapter<>(
                        this, android.R.layout.simple_list_item_multiple_choice,
                        zutatenListe);

        ListView zutatenListeAnsicht = findViewById(R.id.listview_zutaten);
        zutatenListeAnsicht.setAdapter(zutatenverwaltungArrayAdapter);
    }
}

grundgeruestZutatenverwaltung class:

//Daten aus der Datenbank werden als Java Objekte gespeichert, Zugriff auf Variablen mit GETTER und SETTER
package de.der_kalorienzaehler.kalorienzaehler;

import android.database.Cursor;

public class GrundgeruestZutatenverwaltung {

    //Objekte sind private, um Zugriffsmöglichkeiten von außen einzudämmen
    private long id;
    private String zutat;
    private double anzahl;
    private String einheit;
    private int kcal;

    //Konstruktor, Objekte werden erzeugt im Speicher
    public GrundgeruestZutatenverwaltung(long id, String zutat, double anzahl,
                                         String einheit, int kcal){
        this.id = id;
        this.zutat = zutat;
        this.anzahl = anzahl;
        this.einheit = einheit;
        this.kcal = kcal;
    }

    //getter: abrufen
    public long getId(){
        return id;
    }

    //setter: überschreiben
    public void setId(long id){
        this.id = id;
    }

    public String getZutat(){
        return zutat;
    }

    public void setZutat(String zutat){
        this.zutat = zutat;
    }

    public double getAnzahl(){
        return anzahl;
    }

    public void setAnzahl(double anzahl){
        this.anzahl = anzahl;
    }

    public String getEinheit(){
        return einheit;
    }

    public void setEinheit(String einheit){
        this.einheit = einheit;
    }

    public int getKcal(){
        return kcal;
    }

    public void setKcal(int kcal){
        this.kcal = kcal;
    }

    @Override
    public String toString(){
        String ausgabe = zutat + "-" + anzahl + "-" + einheit + "-" + kcal;
        return ausgabe;
    }
}
Trisha
  • 56
  • 3
  • everything seems fine except the last class where you are trying to access the dbZugriff = new DbZugriff(this); TWICE!!! why? in zutat_bearbeiten.java – Rizwan Atta Feb 25 '18 at 15:17
  • I deleted this line and now I have only one error message left: at de.der_kalorienzaehler.kalorienzaehler.zutat_bearbeiten.onCreate(zutat_bearbeiten.java:26) It's this line of code: dbZugriff.open(); When I deleted it, there is a NullPointerException in the following line: datenCursor = dbZugriff.createGrundgeruestZutatenverwaltung("Testprodukt", 2, "kg", 123); But I am happy, that you solved two of the exceptions – Trisha Feb 25 '18 at 15:21
  • GrundgeruestZutatenverwaltung?? is your custom class? that you are using ? – Rizwan Atta Feb 25 '18 at 15:24
  • yes, I can show you the code – Trisha Feb 25 '18 at 15:27
  • i think you need to add a custom adapter – Mohammed Fadhl Feb 25 '18 at 15:48

1 Answers1

0

here is what I have gotten so far by skimming your code! you are directly reading the query outputted cursor into your own model class but you are not handling the worse case scenario that what if your query returns an empty cursor! that can be the issue to the error root try this

   public GrundgeruestZutatenverwaltung createGrundgeruestZutatenverwaltung(
        String zutat, double anzahl, String einheit, int kcal) {
    ContentValues daten_zutat = new ContentValues();
    daten_zutat.put(DbErzeugenUpdaten.COLUMN_ZUTAT, zutat);
    daten_zutat.put(DbErzeugenUpdaten.COLUMN_ANZAHL, anzahl);
    daten_zutat.put(DbErzeugenUpdaten.COLUMN_EINHEIT, einheit);
    daten_zutat.put(DbErzeugenUpdaten.COLUMN_KCAL, kcal);

    //nach id die Daten einfügen
    long idEinfuegen = database.insert(DbErzeugenUpdaten.TABLE_ZUTATENLISTE, null, daten_zutat);

    Cursor cursor = database.query(DbErzeugenUpdaten.TABLE_ZUTATENLISTE, columns,
            DbErzeugenUpdaten.COLUMN_ID + "=" + idEinfuegen, null, null, null, null);

if( cursor.moveToFirst()) {
// it means that your data is entered and cursor has first row to read
GrundgeruestZutatenverwaltung datenCursor = cursorToGrundgeruestZutatenverwaltung(cursor);
        cursor.close();
        return datenCursor;
}     else{
GrundgeruestZutatenverwaltung datenCursor = new GrundgeruestZutatenverwaltung(0,"NULL",0,"Null",0);
return datenCursor;
}
}

and you can do something like this in the ACTIVITY CODE OF YOURS to check whether things are all good or not

//Schreiben in Datenbank
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zutat_bearbeiten);

        dbZugriff = new DbZugriff(this);

        GrundgeruestZutatenverwaltung datenCursor;

        Log.d(LOG_TAG, "Datenquelle wird geöffnet");
        dbZugriff.open();

        datenCursor = dbZugriff.createGrundgeruestZutatenverwaltung("Testprodukt", 2, "kg", 123);
        Log.d(LOG_TAG, "Es wurde der folgende Eintrag in die Datenbank geschrieben:");
        Log.d(LOG_TAG, "ID: " + datenCursor.getId() + ", Inhalt: " + datenCursor.toString());

        Log.d(LOG_TAG, "Folgende Einträge sind in der Datenbank vorhanden:");
        listenEintraegeZeigen();


        dbZugriff = new DbZugriff(this);

        Log.d(LOG_TAG, "Folgender Eintrag in Datenbank: ");
        Log.d(LOG_TAG, "ID" + datenCursor.getId()
                    +   "Zutat" + datenCursor.getZutat()
                    +   "Anzahl" + datenCursor.getAnzahl()
                    +   "Einheit" + datenCursor.getEinheit()
                    +   "Kcal" + datenCursor.getKcal());


        Log.d(LOG_TAG, "Folgende Einträge sind in der Datenbank vorhanden:");

        //Nullpointer Exception, kommt von Methode -> irrelevant
        listenEintraegeZeigen();

        Log.d(LOG_TAG, "Datenquelle wird geschlossen");
        dbZugriff.close();
    }//Schreiben in Datenbank
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zutat_bearbeiten);

        dbZugriff = new DbZugriff(this);

        GrundgeruestZutatenverwaltung datenCursor;

        Log.d(LOG_TAG, "Datenquelle wird geöffnet");
        dbZugriff.open();

        datenCursor = dbZugriff.createGrundgeruestZutatenverwaltung("Testprodukt", 2, "kg", 123);
       if((datenCursor.getZutat()).equalsIgnoreCase("NULL")){
          // no data found etc
       }
    }
Rizwan Atta
  • 3,222
  • 2
  • 19
  • 31
  • unfortunately there is still the error at de.der_kalorienzaehler.kalorienzaehler.zutat_bearbeiten.onCreate(zutat_bearbeiten.java:26) It's this line of code: dbZugriff.open(); So there must be something wrong with dbZugriff – Trisha Feb 25 '18 at 16:06
  • try to check if dbZugriff is null before open() – Mohammed Fadhl Feb 25 '18 at 16:56
  • I tried it, but I still get an error some lines below: datenCursor = dbZugriff.createGrundgeruestZutatenverwaltung("Testprodukt", 2, "kg", 123); – Trisha Feb 25 '18 at 18:27
  • I solved the last problem on my own. Thank you for your help regarding the other to messages :) – Trisha Feb 26 '18 at 15:06
  • good to know please post your solution as your own answer so that it could help others too in future – Rizwan Atta Feb 26 '18 at 15:25