I'm new to android programming! I have a MainActivity in which the onCreate looks like this:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBHandler db = new DBHandler(this);
db.onUpgrade(db.getWritableDatabase(), 1, 2); // I have to figure out how to make the app create the database on install and not on app launch
//Here all tables are filled up. It's hardcoded as the data is not intented to be changed by the user
String ATABLENAME = "aTableName";
db.addKeyPoint(new AKeyPoint(1, "sometext", 167, "areference"), ATABLENAME);
db.addKeyPoint(new AKeyPoint(2, "someothertext", 0, "anotherreference"), ATABLENAME);
}
I also have an InitActivity, that launches upon the press of a button. Within this I have a ListFragment that implements LoaderManager.LoaderCallbacks:
public static class KeyFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>{
private SimpleCursorAdapter adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// the desired columns to be bound
String[] columns = new String[] { "question1","answer1" };
// the XML defined views which the data will be bound to
int[] to = new int[] { R.id.question, R.id.answer };
adapter = new SimpleCursorAdapter(getActivity(),R.layout.key_list_entry, null, columns, to, 0);
this.setListAdapter(adapter);
LoaderManager lm = this.getLoaderManager();
lm.initLoader(1, null, this);
}
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
final SimpleCursorLoader scloader = new SimpleCursorLoader(getActivity()) {
@Override
public Cursor loadInBackground() {
final DBHandler db = new DBHandler(getActivity());
Cursor c = db.getKeyPointCursor(1, "Crataegus");
db.close();
return c;
}
};
return scloader;
}
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
adapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
}
}
I use the the SimpleCursorLoader with the LoaderManager. It can be found here: https://github.com/browep/AndroidCursorLoaderTutorial/blob/master/src/com/github/browep/cursorloader/SimpleCursorLoader.java . In my onCreateLoader the loadInBackGround retrieves a Cursor in the following way
Cursor c = db.getKeyPointCursor(anInt, "aTableName");
and returns it.
In my databasehandler (db) the getKeyPointCursor looks like this:
public Cursor getKeyPointCursor(int keyPointID, String tableName){
Log.v("bae", "Now in getKeyPointCursor, attempting to get readable database");
SQLiteDatabase db = this.getReadableDatabase();
Log.v("bae", "Success... attempting to obtain a cursor");
Cursor cursor = db.query(tableName, null, KEY_POINTID + "=?",
new String[] { String.valueOf(keyPointID) }, null, null, null, null);
Log.v("bae", "Success... closing db and returning cursor");
db.close();
return cursor;
}
It prints the "Now in getKeyPointCursor, attempting to get readable database" and then throws a NullPointerException:
09-19 19:27:39.920: W/dalvikvm(3055): threadid=11: thread exiting with uncaught exception (group=0x40c7c1f8)
09-19 19:27:39.925: E/AndroidRuntime(3055): FATAL EXCEPTION: ModernAsyncTask #1
09-19 19:27:39.925: E/AndroidRuntime(3055): java.lang.RuntimeException: An error occured while executing doInBackground()
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.lang.Thread.run(Thread.java:856)
09-19 19:27:39.925: E/AndroidRuntime(3055): Caused by: java.lang.NullPointerException
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:231)
09-19 19:27:39.925: E/AndroidRuntime(3055): at jem.danskflora.DBHandler.getKeyPointCursor(DBHandler.java:235)
09-19 19:27:39.925: E/AndroidRuntime(3055): at jem.danskflora.InitKeyActivity$KeyFragment$1.loadInBackground(InitKeyActivity.java:79)
09-19 19:27:39.925: E/AndroidRuntime(3055): at jem.danskflora.SimpleCursorLoader.loadInBackground(SimpleCursorLoader.java:1)
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
09-19 19:27:39.925: E/AndroidRuntime(3055): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
09-19 19:27:39.925: E/AndroidRuntime(3055): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-19 19:27:39.925: E/AndroidRuntime(3055): ... 4 more
I'm suspecting that I'm not working on the same database somehow or maybe that I pass the wrong context to my databasehandler? Anyways I desperately need help to solve this!
I would say that the reason for that exception is this line:
private DBHandler db = new DBHandler(getActivity());
at that moment getActivity()
most likely returns null
as the Fragment
isn't attached yet and this Context
reference is used in the getReadableDatabase()
and getWritableDatabase()
methods. Try to initialize the db
reference from the KeyFragment
in onActivityCreated
, the Activity
reference will be available there.
Also, avoid this:
db.onUpgrade(db.getWritableDatabase(), 1, 2);