使用AsyncTask和SQLite游标的NullPointerException

时间:2012-02-12 23:15:31

标签: android sqlite cursor android-asynctask

好的,我很难过。我有一个我发布的应用程序有错误ANR keyDispatchingTimedOut所以在修复它时,我以为我会使用AsyncTask访问我的数据库,但我一直在获取NPE。此外,在我单击“添加”按钮然后单击“返回”之前,它不会填充列表视图,因此它会在onResume中填充listview,但不会填充onCreate。这是活动代码。

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);

    }

}

}

这是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)

这是logcat中提到的DBase代码。

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);
}

我知道我必须遗漏一些东西。我尝试将startManagingCursor(c);放在onPostExecute中,在onCreate中初始化dbase并使用asyncTask来提取数据等。

任何帮助将不胜感激。

这里编辑的是DBase类的其余部分。在我尝试使用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 );
}

}

1 个答案:

答案 0 :(得分:1)

对不起,比尔,那是一种躲闪的小屋。您正在启动一个AsyncTask,该AsyncTask应该填充实例变量c,然后在startManagingCursor()运行第一行之前几乎肯定立即调用c上的AsyncTask。我强烈怀疑这就是为什么它适用于onResume而不是onCreate,因为onResume实际上会填充c

就个人而言,如果您真的希望将所有内容都基于AsyncTask,那么将所有基于AsyncTask。在startManagingCursor()之前请勿setListAdapter()onPostExecute()

不知道你的DBView内部正在发生什么,尽管最有可能来自发布的代码,ourDatabase此时为空。