2012-09-10 96 views
3

我完全不熟悉android編程。我可以看到這個問題以前已經提出過很多次了。但是,我仍然無法看到問題所在。我試圖將數據從SQLite數據庫連接到列表視圖。在ListActivity我的onCreate如下所示:IllegalStateException:嘗試重新打開已關閉的對象。 SimpleCursorAdapter問題

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_init_key); 
    getActionBar().setDisplayHomeAsUpEnabled(true); 

    DBHandler db = new DBHandler(this); 

    Cursor cursor = db.getKeyPointCursor(1, "Crataegus"); 
    // 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 }; 

    SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.key_list_entry, cursor, columns, to, 0); 

    cursor.close(); 
    this.setListAdapter(mAdapter); 

} 

它提出了以下異常,我希望有人能幫助我。

09-10 21:52:01.505: W/dalvikvm(10976): threadid=1: thread exiting with uncaught exception (group=0x40c8e1f8) 
09-10 21:52:01.510: E/AndroidRuntime(10976): FATAL EXCEPTION: main 
09-10 21:52:01.510: E/AndroidRuntime(10976): java.lang.RuntimeException: Unable to start activity ComponentInfo{jem.danskflora/jem.danskflora.InitKeyActivity}: java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT * FROM Crataegus WHERE _id=?) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1970) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1995) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread.access$600(ActivityThread.java:128) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1161) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.os.Handler.dispatchMessage(Handler.java:99) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.os.Looper.loop(Looper.java:137) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread.main(ActivityThread.java:4514) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at java.lang.reflect.Method.invokeNative(Native Method) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at java.lang.reflect.Method.invoke(Method.java:511) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at dalvik.system.NativeStart.main(Native Method) 
09-10 21:52:01.510: E/AndroidRuntime(10976): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: android.database.sqlite.SQLiteQuery (mSql = SELECT * FROM Crataegus WHERE _id=?) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:33) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:82) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:156) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.widget.CursorAdapter.getCount(CursorAdapter.java:196) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.widget.ListView.setAdapter(ListView.java:467) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ListActivity.setListAdapter(ListActivity.java:265) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at jem.danskflora.InitKeyActivity.onCreate(InitKeyActivity.java:30) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.Activity.performCreate(Activity.java:4562) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1053) 
09-10 21:52:01.510: E/AndroidRuntime(10976): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1934) 
09-10 21:52:01.510: E/AndroidRuntime(10976): ... 11 more 

回答

4

請勿在onCreate方法中關閉遊標。它由適配器引用,但尚未使用!

嘗試使用LoaderManager/CursorLoader。這是處理光標的新途徑:How to transition from managedQuery to LoaderManager/CursorLoader?

這裏是我的一個項目爲例(我沒有測試此代碼):

public class AdditionalActivitiesListFragment extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener, OnClickListener 
{ 
    private SimpleCursorAdapter adapter; 


    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     String[] columns = new String[] { "your", "db", "columns" }; 
     int[] to = new int[] { R.id.your, R.id.fields, R.id.toMapWith }; 

     getLoaderManager().initLoader(0x02, null, this); 

     adapter = new SimpleCursorAdapter(activity.getApplicationContext(), R.layout.row_layout, null, columns, to, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); 
     setListAdapter(adapter); 
    } 

    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) 
    { 
     return new SimpleCursorLoader(this) { 
      @Override 
      public Cursor loadInBackground() { 
       Cursor c = // Your cursor 

       return c; 
      } 
     }; 
    } 

    public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) 
    { 
     adapter.swapCursor(cursor); 
    } 

    public void onLoaderReset(Loader<Cursor> arg0) 
    { 
     adapter.swapCursor(null); 
    } 
} 

的SimpleCursorLoader來源:https://gist.github.com/1217628(通過https://stackoverflow.com/a/7422343/615882

+0

非常感謝您的回答!您使用的SimpleCursorLoader是這裏提出的:http://stackoverflow.com/questions/7182485/usage-cursorloader-without-contentprovider? – Greforb

+0

並且:在您的OnLoadFinished和OnLoaderReset中,您使用的適配器在onCreate中定義。你將如何處理?對不起,但它有時真的讓我很煩惱,Java不會猜測我的想法:) – Greforb

+0

@Greforb哦,是的,請原諒我,我忘記了精簡SimpleCursorLoader的來源。是的,這是一個! :) 適配器在'onCreate()'中定義,並且是您的活動的屬性(在我的情況下它是一個ListActivity,因此''setListAdapter()'調用) –

0

我覺得cursor繼續由adapter使用,所以你可能不應該關閉它在那裏。

您可以使用Activity.startManagingCursor()Activity會在您不再使用時爲您關閉。

+0

但是,這種方法是不推薦使用的權利?這實際上很奇怪,據我所知,如果你使用SQLite數據庫存儲數據,就沒有真正簡單的選擇,你必須做各種解決方法。使用LoaderManager/CursorLoader你必須使用ContentProvider,還是我完全錯了? – Greforb

1

您的SimpleCursorAdapter綁定到您的光標,它將「提供」您的適配器與來自光標的數據。把你的適配器看作是一個適配器,它位於你的Cursor之上,並處理從你的Cursor到你的ListView的數據委託。所以,當你不再使用你的ListView時,你應該只關閉你的Cursor,fx。在onPause()(當活動不再向用戶顯示時)。

相關問題