Исключение NullPointerException с AsyncTask и курсором SQLite - PullRequest
1 голос
/ 13 февраля 2012

Хорошо, я в тупике. У меня есть приложение, которое я опубликовал, с ошибкой ANR keyDispatchingTimedOut, поэтому, исправляя это, я думал, что получу доступ к своей БД с помощью AsyncTask, но продолжаю получать NPE. Кроме того, он не заполняет представление списка, пока я не нажму кнопку добавления, а затем не нажму назад, поэтому он заполняет представление списка в onResume, но не в 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)

А вот код DBase, упомянутый в 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);
}

Я знаю, что я что-то упускаю. Я попытался поместить startManagingCursor(c); в onPostExecute, инициализировать базу данных в onCreate и использовать 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 Ответ

1 голос
/ 13 февраля 2012

Извините, Билл, это что-то вроде мешанины. Вы запускаете AsyncTask, который должен заполнить переменную экземпляра c, а затем немедленно вызываете startManagingCursor() для c почти наверняка до того, как AsyncTask запустит первую строку. Я сильно подозреваю, что именно поэтому он работает в onResume вместо onCreate, поскольку onResume будет иметь заполненный c.

Лично, если вы действительно хотите основать все на AsyncTask, подставьте все на AsyncTask. Не startManagingCursor() или setListAdapter() до onPostExecute().

Понятия не имею, что происходит внутри вашего DBView в NPE, хотя, скорее всего, из опубликованного кода, что ourDatabase в этот момент нулевое.

...