【问题标题】:Am I working on the same database? getReadableDatabase() throws nullpointerexception我在同一个数据库上工作吗? getReadableDatabase() 抛出空指针异常
【发布时间】:2012-09-19 18:11:54
【问题描述】:

我是安卓编程新手!我有一个 MainActivity,其中 onCreate 看起来像这样:

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

我还有一个 InitActivity,它会在按下按钮时启动。在此我有一个实现 LoaderManager.LoaderCallbacks 的 ListFragment:

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

}

我将 SimpleCursorLoader 与 LoaderManager 一起使用。可以在这里找到:https://github.com/browep/AndroidCursorLoaderTutorial/blob/master/src/com/github/browep/cursorloader/SimpleCursorLoader.java。 在我的 onCreateLoader 中,loadInBackGround 以下列方式检索 Cursor

Cursor c = db.getKeyPointCursor(anInt, "aTableName");

并返回它。

在我的数据库处理程序 (db) 中,getKeyPointCursor 如下所示:

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

它打印“现在在 getKeyPointCursor,试图获取可读数据库”,然后抛出 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

我怀疑我没有在同一个数据库上工作,或者我可能将错误的上下文传递给我的数据库处理程序?无论如何,我迫切需要帮助来解决这个问题!

【问题讨论】:

  • 你的怀疑可能是真的,也可能不是,但是没有看到对SQLiteOpenHelper的构造函数的调用,没有人可以证实这一点。
  • 啊,是的,我以为我错过了一些非常相关的东西。我现在相应地编辑了 InitKeyActivity。好吗?

标签: android sqlite cursor nullpointerexception android-listfragment


【解决方案1】:

我会说该异常的原因是这一行:

private DBHandler db = new DBHandler(getActivity());

此时getActivity() 很可能返回null,因为Fragment 尚未附加,并且此Context 引用用于getReadableDatabase()getWritableDatabase() 方法。尝试从onActivityCreated 中的KeyFragment 初始化db 引用,Activity 引用将在那里可用。

另外,避免这种情况:

db.onUpgrade(db.getWritableDatabase(), 1, 2); 

【讨论】:

  • 我现在试过了,但是我的 onCreateLoader 函数无法使用 db。我已经编辑了上面的代码,所以你可以看到所有的。如您所见,我现在尝试在 onCreateLoader 函数上初始化数据库。它在 loadInBackground 中到达 return c (我认为它实际上返回了游标),但随后它抱怨数据库已经关闭。希望有人能明白为什么?它没有完成 initLoader 所以这里可能发生了什么? initloader 是否尝试访问已经以某种方式关闭的数据库?
  • @Greforb 如果你想让Cursor 有效,你不能关闭数据库连接,所以删除db.close(); 行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 2020-11-22
  • 2020-08-10
  • 2013-03-21
相关资源
最近更新 更多