Elad Benda2
Elad Benda2

Reputation: 15482

java.lang.NullPointerException at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)

I cannot understand how am i initializing the DB wrong:

java.lang.NullPointerException
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
        at com.example.stopcall.app.dal.PhoneDal.getItem(PhoneDal.java:105)
        at com.example.stopcall.app.ItemDetailFragment$1.onClick(ItemDetailFragment.java:87)
        at android.view.View.performClick(View.java:4654)
        at android.view.View$PerformClick.run(View.java:19438)
        at android.os.Handler.handleCallback(Handler.java:733)

the code falls on this line: SQLiteDatabase db = this.getWritableDatabase();

from this code:

public class PhoneDal extends SQLiteOpenHelper {

    // Database Version
    private static final int DATABASE_VERSION = 1;
    // Database Name
    private static final String DATABASE_NAME = Constants.DB_NAME;

    private static final String BLOCKED_PHONES_TABLE = "BLOCKED_PHONES_TABLE";
    private static final String COMMENTS_TABLE = "COMMENTS_TABLE";

    public PhoneDal(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // SQL statement to create book table

        String CREATE_BLOCKED_PHONES_TABLE = "CREATE TABLE "
                + BLOCKED_PHONES_TABLE + " ( "
                + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "phone TEXT, "
                + "isBlocked BIT )";

        db.execSQL(CREATE_BLOCKED_PHONES_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (newVersion > oldVersion) {
            Log.w("MyAppTag", "Updating database from version " + oldVersion
                    + " to " + newVersion + " .Existing data will be lost.");
            // Drop older books table if existed
            db.execSQL("DROP TABLE IF EXISTS " + BLOCKED_PHONES_TABLE);

            // create fresh books table
            this.onCreate(db);
        }

    }



    private static final String KEY_ID = "id";
    private static final String KEY_PHONE = "KEY_PHONE";
    private static final String KEY_IS_BLOCKED = "KEY_IS_BLOCKED";

    public void addItem(Phone phone) {
        // 1. get reference to writable DB
        SQLiteDatabase db = this.getWritableDatabase();

initialization code:

public class ItemDetailFragment extends Fragment {
    /**
     * The fragment argument representing the item ID that this fragment
     * represents.
     */
    public static final String ARG_ITEM_ID = "item_id";

    /**
     * The dummy content this fragment is presenting.
     */
    private DummyContent.DummyItem mItem;
    private PhoneDal phoneDal;
    private CommentDal commentDal;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public ItemDetailFragment() {
        this.mItem = mItem;
        this.phoneDal = new PhoneDal(getActivity());
        this.commentDal = new CommentDal(getActivity());
    }

    @SuppressLint("ValidFragment")
    public ItemDetailFragment(DummyContent.DummyItem mItem, PhoneDal phoneDal, CommentDal commentDal) {
        this.mItem = mItem;
        this.phoneDal = phoneDal;
        this.commentDal = commentDal;
    }

Upvotes: 1

Views: 3531

Answers (2)

wvdz
wvdz

Reputation: 16651

You are initializing PhoneDal with null as context, which causes the NPE later on. The problem is that you call getActivity() in a constructor of your Fragment, at which point it will return null.

Don't implement a constructor for View components like Activities and Fragment!

Instead, use the dedicated methods like onCreate, OnStart, OnAttach to initialize and manipulate them.

This is also mentioned in the Javadoc of the constructor of Fragment:

Applications should generally not implement a constructor. The first place application code an run where the fragment is ready to be used is in onAttach(Activity), the point where the fragment is actually associated with its activity.

For more info on the Fragment lifecycle: Fragments

Incidentally, it is adviced to use the application context for initializing your SQLiteOpenHelper: Avoid memory leaks

Upvotes: 0

laalto
laalto

Reputation: 152827

public ItemDetailFragment() {
    this.phoneDal = new PhoneDal(getActivity());

Fragment constructor is too early to call getActivity() - it will return null. Passing a null as Context in SQLiteOpenHelper constructor causes the exception when get...Database() is invoked.

Postpone your PhoneDal initialization to onAttach() or later in the fragment lifecycle.

Upvotes: 3

Related Questions