0

我是新來的android編程!我有一個MainActivity,其中onCreate看起來像這樣:我工作在同一個數據庫嗎? getReadableDatabase()拋出nullpointerexception

@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 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 

我懷疑我不是以某種方式在同一個數據庫上工作,或者是我將錯誤的上下文傳遞給了我的數據庫處理程序?無論如何,我非常需要幫助來解決這個問題!

+0

你懷疑可能是真實的,或不是,但沒有人可以證實這一點,沒有看到調用'SQLiteOpenHelper'的構造。 –

+0

啊,是的,我以爲我錯過了一些相關的東西。我現在相應地編輯了InitKeyActivity。好? – Greforb

回答

7

我要說的是,對於異常的原因是這一行:

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

在那一刻getActivity()最有可能返回null作爲Fragment尚未連接,這Context引用在getReadableDatabase()使用, getWritableDatabase()方法。嘗試在onActivityCreated中初始化參考KeyFragmentdbActivity參考將在那裏可用。

此外,避免這種情況:

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

我現在試過了,但是th數據庫不適用於我的onCreateLoader函數。我已經編輯了上面的代碼,所以你可以看到所有的代碼。正如你所看到的,我現在嘗試初始化onCreateLoader函數中的db。它到達了loadInBackground中的return c(我認爲它實際上返回了遊標),但它抱怨數據庫已經關閉。希望有人能看到爲什麼?它沒有完成initLoader,所以這裏可能發生了什麼? initloader是否嘗試訪問已經關閉的db? – Greforb

+0

@Greforb如果你希望'Cursor'有效,你不能關閉數據庫連接,所以刪除'db.close();'行。 – Luksprog

+0

它似乎工作,非常感謝! – Greforb

相關問題