1

I have an app with multiple fragments. In one fragment the user enters information which gets stored into a sql table. In another fragment, data is read from that table (currently just logging it to console for testing purposes). Saving to the db works fine, but when I try to read the data I get an error.

My DBHelper class has these read/insert methods:

public class DBHelper extends SQLiteOpenHelper {

    public boolean insertSubject(Integer id, String date, String RA, Integer condition, Integer age, String sex)
    {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(SUBJECTS_ID, id);
        contentValues.put(SUBJECTS_DATE, date);
        contentValues.put(SUBJECTS_RA, RA);
        contentValues.put(SUBJECTS_CONDITION, condition);
        contentValues.put(SUBJECTS_AGE, age);
        contentValues.put(SUBJECTS_SEX, sex);
        db.insertOrThrow(SUBJECTS_TABLE_NAME, null, contentValues);
        db.close();
        return true;
    }

    public boolean getSubject(Short subNum){
        SQLiteDatabase db = this.getReadableDatabase();
        String query = "SELECT * FROM subjects WHERE " + SUBJECTS_ID + "=" + subNum;

        Cursor c = db.rawQuery(query, null);

        while (c.moveToNext()) {
            String result_0=c.getString(0);
            String result_1=c.getString(1);

            Log.d("query", result_0);
            Log.d("query", result_1);
        }
        c.close();
        db.close();

        return true;
    }
}

In my user creation fragment, I create a new DBHelper:

@Override
public void onActivityCreated(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
    db = new DBHelper(getActivity());
}

Then the view is created:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        coordinatorLayout = (CoordinatorLayout) getActivity().findViewById(R.id.coordinator_layout);
        View view = inflater.inflate(R.layout.fragment_new, container, false);

        mainActivity = (MainActivity) getActivity();

        //Listener for create button
        createButton = (Button) view.findViewById(R.id.input_submit);
        createButton.setOnClickListener(this);

        // Inflate the layout for this fragment
        return view;
    }

The create button has an onClick listener:

@Override
public void onClick(View v) {

    //Some form validation things go here

        //write to database
        try {
            db.insertSubject(
                    Integer.parseInt(subNum),
                    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
                    ra,
                    Integer.parseInt(condition),
                    Integer.parseInt(age),
                    sex);

            //Store subject number for use throughout
            mainActivity.subNum = Short.parseShort(subNum);
            mainActivity.subCreated = true;

        } catch (SQLiteConstraintException e){
            Snackbar.make(coordinatorLayout, "Subject number already exists", Snackbar.LENGTH_SHORT).show();
            subNumWrapper.requestFocus();
        }
}

All of this saves to the DB fine. The sub number is saved to the main activity so I can use that later when querying the database

However, when trying to read from the db I have some problems. In that fragment, my onActivityCreated method is literally identical to the fragment above. And then in onCreateView, basically the same as above but with the addition of calling the DBHelper method:

db.getSubject(mainActivity.subNum);

I'm getting the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean come.example.test.DBHelper.getSubject(java.lang.Short)' on a null object reference

I think that means it isn't aware of the existence of db?

Why would that be given I have defined db in the exact same way (in onActivityCreated) in both of the fragment classes? Why would this work in the subject creation fragment, but not in the querying frament?

Simon
  • 9,762
  • 15
  • 62
  • 119
  • see http://stackoverflow.com/a/32656807/3697191 onActivityCreated() is called after onCreateView() . In your insertion fragment, insertion takes place on click, which is event driven and by the time, onActivityCreated() would have been executed. While reading from db this won't be the case. – chiragjn Mar 19 '16 at 11:24

1 Answers1

0

To keep it original,

The answer you are looking for is here : https://stackoverflow.com/a/32656807/3697191

In your insertion fragment, calls happen in order something like this

onCreateView() //db still null
onActivityCreated() //db instantiated
onClick() //User clicked, db is not null

while in your reading from db fragment

onCreateView() //db still null
//Uh oh, we tried to read from db, NullPointerException
onActivityCreated() //db instantiated
Community
  • 1
  • 1
chiragjn
  • 764
  • 11
  • 31
  • so does this mean most/all db read/write code (in general) should exist in `onActivityCreated()` then? – Simon Mar 19 '16 at 12:15
  • If you are going to need to present data in view, then do the db work(instantiating and fetching) in onCreateView(). but consider doing the db work in background thread and updating views as soon as data is fetched, because if data fetch takes long and if done on UI thread,it might make your app unresponsive – chiragjn Mar 19 '16 at 12:23