Question

I am trying to use a singleton class to create this database because I need it to be open for each of the activities in the application. I keep getting a null pointer error from either the "getFilesDir" or "if(instance == null) calls, and since I am not that familiar with android programming I am not sure what is going on.

package com.database;

import java.io.File;

import android.app.Application;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;

import com.businessclasses.Field;
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.config.AndroidSupport;
import com.db4o.config.EmbeddedConfiguration;

public final class anotherTest extends Application {
    private static ObjectContainer playsDB;
    private static ObjectContainer gamePlanDB;

    private anotherTest instance;

    public anotherTest(){

        final EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
        config.common().add(new AndroidSupport());
        //instance.getFilesDir().getPath()
        new File(getFilesDir().getPath(), "/PlaysDB.db4o").delete();

        Log.d("db", "" + instance.getFilesDir().getPath());
        //getFilesDir().getPath();
        //String appPath = "/data/data/PlaysDB/database";

        playsDB = Db4oEmbedded.openFile(config, getFilesDir().getPath() +     "/PlaysDB.db4o");
        //File test = new File(appPath + "/PlaysDB.db4o");
        //if(test != null){
        //  Log.d("db", "file was created");
        //  Log.d("db", "path >> " + test.getAbsolutePath());
            //test.delete();
        //}

        //playsDB = Db4oEmbedded.openFile(config, appPath + "/PlaysDB.db4o");
    }

    public synchronized anotherTest getInstance(){
        if(instance == null){
            instance = new anotherTest();
        }
        return instance;
    }

    public void storePlay(Field field){
        if(field != null){
            if(playsDB == null){
                Log.d("db", "database is null");
            }
            playsDB.store(field);
            playsDB.commit();
            Log.d("added play", "play added to db");    
        }
        else{
            Log.e("field input null", "play not added to db");
        }
    }   
}

And here is my call in one of the activities.

   public void onClick(View v) {
        String formation = playFormation.getText().toString();
        String name = playName.getText().toString();
        String type = playType.getSelectedItem().toString();
        //TODO:send to database

        Field newField = new Field();
        newField.setPlayName(name);
        newField.setPlayType(type);

        anotherTest temp = new anotherTest();
        temp.getInstance().storePlay(newField);
    }

Have been trying to make this database work for the past few weeks to no avail. Any help or guidance would be greatly appreciated.

Was it helpful?

Solution

The way this is structured doesn't make sense.

  • Java classes are always named with proper case - so it should be "AnotherTest".
  • You're not actually creating a singleton, because neither your instance, nor your getInstance() are static. Also, you never access your instance via "getInstance()".
  • You have a class AnotherTest, which has as a field an instance of AnotherTest, which is never, ever initialised, and which is accessed in the constructor of AnotherTest. This is just guaranteed to be null.
  • You are relying on implicit state of the Application superclass, which is never, ever provided because Application is supposed to be declared in the androidmanifest.xml, where it will be constructed for you. Meanwhile, you are constructing an instance manually in your event handler, so it has none of the state you expect - but anyway, it will fall over in its own constructor because it tries to reference a null pointer to itself, as mentioned above.

Your problems are nothing to do with DB40, and everything to do with not understanding what you're doing.

It needs to be way more like:

public final class AnotherTest {


    private static AnotherTest instance;

    private final Context context;

    private AnotherTest(Context context){
        this.context = context;

        // Do whatever you need to do with DB4O using *only* the supplied context here
    }

    public static synchronized AnotherTest getInstance(Context context){
        if(instance == null){
            instance = new AnotherTest(context);
        }
        return instance;
    }
}

And in the event handler:

AnotherTest.getInstance(Context.getApplicationContext()).storePlay(newField);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top