Ok, I’m stumped. I have an app that I’ve published that had the error ANR keyDispatchingTimedOut so while fixing that, I thought I’d access my DB with AsyncTask but I keep getting an NPE. Also, it doesn’t populate the listview until I click the add button then click back, so it’s populating the listview in onResume but not onCreate. Here is the activity code.
public class View extends ListActivity implements OnClickListener {
String loc;
SharedPreferences data;
public static String filename = "Location";
private DBase db;
public static String vLoc = null, vId = null, vSong = null, vNumber = null;
Button bNLAdd, bNLBack;
TextView tvNLList;
Cursor c;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.notepad_list);
getLoc();
initialize();
fillData();
}
@Override
public void onClick(android.view.View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.bNLAdd:
startActivity(new Intent("com.ADD")); // edited to remove package name
break;
case R.id.bNLBack:
finish();
break;
}
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
fillData();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (c != null && !c.isClosed()) {
c.close();
}
db.close();
}
@Override
protected void onListItemClick(ListView l, android.view.View v,
int position, long id) { // TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
vLoc = loc;
vId = (String) ((Cursor) l.getItemAtPosition(position)).getString(0);
vSong = (String) ((Cursor) l.getItemAtPosition(position)).getString(1);
vNumber = (String) ((Cursor) l.getItemAtPosition(position))
.getString(2);
startActivity(new Intent("com.EDIT")); // edited to remove package name
}
private void fillData() {
// Get all of the notes from the database and create the item list
new getCursor().execute(loc);
startManagingCursor(c);
String[] from = new String[] { DBase.KEY_2SONG, DBase.KEY_2NUMBER };
int[] to = new int[] { R.id.text1, R.id.text2 };
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.notes_row, c, from, to);
setListAdapter(notes);
}
private void getLoc() {
// TODO Auto-generated method stub
data = getSharedPreferences(filename, 0);
loc = data.getString("loc", null);
}
private void initialize() {
// TODO Auto-generated method stub
tvNLList = (TextView) findViewById(R.id.tvNLList);
tvNLList.setText("Song List for Location " + loc);
bNLAdd = (Button) findViewById(R.id.bNLAdd);
bNLBack = (Button) findViewById(R.id.bNLBack);
bNLAdd.setOnClickListener(this);
bNLBack.setOnClickListener(this);
}
public class getCursor extends AsyncTask<String, Integer, Cursor> {
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
@Override
protected Cursor doInBackground(String... params) {
// TODO Auto-generated method stub
db = new DBase(View.this);
db.open();
try {
c = db.fetchData(loc);
} catch (NullPointerException e) {
// TODO: handle exception
e.printStackTrace();
} finally {
if (c != null) {
return c;
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Cursor c) {
// TODO Auto-generated method stub
super.onPostExecute(c);
}
}
}
And here is the logcat.
02-12 16:10:03.834: WARN/System.err(549): java.lang.NullPointerException
02-12 16:10:04.074: WARN/System.err(549): at com.DBase.fetchData(DBase.java:89)
02-12 16:10:04.074: WARN/System.err(549): at com.View$getCursor.doInBackground(View.java:134)
02-12 16:10:04.074: WARN/System.err(549): at com.View$getCursor.doInBackground(View.java:1)
02-12 16:10:04.074: WARN/System.err(549): at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-12 16:10:04.074: WARN/System.err(549): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
02-12 16:10:04.074: WARN/System.err(549): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
02-12 16:10:04.074: WARN/System.err(549): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
02-12 16:10:04.074: WARN/System.err(549): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
02-12 16:10:04.074: WARN/System.err(549): at java.lang.Thread.run(Thread.java:1096)
And here is the DBase code mentioned in the logcat.
public Cursor fetchData(String loc) {
// TODO Auto-generated method stub
return ourDatabase.query(loc, new String[] { KEY_ROWID, KEY_2SONG, KEY_2NUMBER },
null, null, null, null, null);
}
I know i must be missing something. I tried putting the startManagingCursor(c); in the onPostExecute, initializing the dbase in onCreate and using the asyncTask to just pull the data, etc.
Any help will be appreciated.
EDIT here is the rest of the DBase class. It was working perfectly until I tried AsyncTask.
public class DBase {
public static final String KEY_ROWID = "_id";
public static final String KEY_2TBL = "loc";
public static final String KEY_2SONG = "Song";
public static final String KEY_2NUMBER = "Number";
private static final String DATABASE_NAME = "Tracker";
static final String DATABASE_TABLE = "TempTable";
private static final int DATABASE_VERSION = 1;
private DbHelper ourHelper;
private final Context ourContext;
private SQLiteDatabase ourDatabase;
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" + KEY_ROWID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_2TBL
+ " TEXT NOT NULL, " + KEY_2NUMBER + " TEXT NOT NULL, "
+ KEY_2SONG + " TEXT NOT NULL);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
public DBase(Context c) {
ourContext = c;
}
public DBase open() throws SQLException {
ourHelper = new DbHelper(ourContext);
ourDatabase = ourHelper.getWritableDatabase();
return this;
}
public void close() {
ourHelper.close();
}
public void deleteEntry(long dId, String loc) {
ourDatabase.delete(loc, KEY_ROWID + "=" + dId, null);
}
public long addTable(String loc) {
// TODO Auto-generated method stub
ourDatabase.execSQL("CREATE TABLE IF NOT EXISTS " + loc + " ("
+ KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_2TBL
+ " TEXT NOT NULL, " + KEY_2SONG + " TEXT NOT NULL, "
+ KEY_2NUMBER + " TEXT NOT NULL);");
ContentValues cv = new ContentValues();
cv.put(KEY_2TBL, loc);
return ourDatabase.insert(loc, null, cv);
}
public Cursor fetchData(String loc) {
// TODO Auto-generated method stub
return ourDatabase.query(loc, new String[] { KEY_ROWID, KEY_2SONG, KEY_2NUMBER },
null, null, null, null, null);
}
public long createEntry(String loc, String sSong, String sNumber) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues();
cv.put(KEY_2TBL, loc);
cv.put(KEY_2SONG, sSong);
cv.put(KEY_2NUMBER, sNumber);
return ourDatabase.insert(loc, null, cv);
}
public ArrayList<String> listTables() {
ArrayList<String> tableList = new ArrayList<String>();
String SQL_GET_ALL_TABLES = "SELECT name FROM "
+ "sqlite_master WHERE type='table' ORDER BY name";
Cursor c = ourDatabase.rawQuery(SQL_GET_ALL_TABLES, null);
c.moveToFirst();
if (!c.isAfterLast()) {
do {
tableList.add(c.getString(0));
} while (c.moveToNext());
}
c.close();
return tableList;
}
public void editSong(long eId, String loc, String eSong, String eNumber) {
// TODO Auto-generated method stub
ContentValues cvUpdate = new ContentValues();
cvUpdate.put(KEY_2TBL, loc);
cvUpdate.put(KEY_2SONG, eSong);
cvUpdate.put(KEY_2NUMBER, eNumber);
ourDatabase.update(loc, cvUpdate, KEY_ROWID + "=" + eId, null);
}
public void deleteTable(String loc) {
// TODO Auto-generated method stub
ourDatabase.execSQL("DROP TABLE " + loc );
}
}
Sorry, Bill, that’s kind of a hodge-podge. You’re kicking off an AsyncTask that’s supposed to populate an instance variable
c, then immediately callingstartManagingCursor()oncalmost certainly before theAsyncTaskhas run the first line. I strongly suspect that’s why it works inonResumeinstead ofonCreatesinceonResumewill actually have a populatedc.Personally, if you really want to base everything off an AsyncTask, base everything off the AsyncTask. Don’t
startManagingCursor()orsetListAdapter()untilonPostExecute().No idea what’s going on internally in your
DBViewto NPE, though it’s most likely from the posted code that it’sourDatabasethat’s null at that point.