将CursorAdapter附加到SQLiteQuery时出错:尝试重新打开已关闭的对象

时间:2017-07-05 22:04:42

标签: android sqlite android-cursoradapter

活动代码:

public class ShowRawDB extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_raw_db);
        displayDatabaseInfo();
    }
    private void displayDatabaseInfo() {
        DatabaseHelper DBHelper = new DatabaseHelper(this);
        SQLiteDatabase db = DBHelper.getReadableDatabase();
        String[] projection = {
                DBHelper.COL_ID,
                DBHelper.COL_DATE,
                DBHelper.COL_PUNCHIN
        };
        String sortOrder =
                DBHelper.COL_DATE + " DESC";
        Cursor cursor = db.query(
                DBHelper.TABLE_NAME,                     // The table to query
                projection,                               // The columns to return
                null,                                // The columns for the WHERE clause
                null,                            // The values for the WHERE clause
                null,                                     // don't group the rows
                null,                                     // don't filter by row groups
                sortOrder                                 // The sort order
        );
        ListView lst = (ListView) findViewById(R.id.listDB);
        DBAdapter MyAdapter = new DBAdapter(this, cursor);
        lst.setAdapter(MyAdapter);
        MyAdapter.changeCursor(cursor);
        cursor.close();
    }
}

我的游标适配器:

public class DBAdapter extends CursorAdapter {
    public DBAdapter(Context context, Cursor cursor) {
        super(context, cursor, 0);
    }
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
        return LayoutInflater.from(context).inflate(R.layout.item_punchlist, viewGroup, false);
    }
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // Find fields to populate in inflated template
        TextView txtDate = (TextView) view.findViewById(R.id.itemNum);
        TextView txtItemID = (TextView) view.findViewById(R.id.itemDate);
        // Extract properties from cursor
        String itemDate = cursor.getString(cursor.getColumnIndexOrThrow("DBHelper.COL_DATE"));
        int itemID = cursor.getInt(cursor.getColumnIndexOrThrow("DBHelper.COL_ID"));
        // Populate fields with extracted properties
        txtDate.setText(itemDate);
        txtItemID.setText(String.valueOf(itemID));
    }
}

数据库助手:

package su.joel.punchintime;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public final class DatabaseHelper extends SQLiteOpenHelper {
        public static final String TABLE_NAME = "punchlog";
        public static final String COL_ID = "_id";
        public static final String COL_DATE = "date";
        public static final String COL_PUNCHIN = "punchin";
        public static final String COL_PUNCHOUT = "punchout";
        public static final String COL_ONDUTY = "onduty";
        public static final String COL_FORGOTIN = "forgotin";
        public static final String COL_FORGOTOUT = "forgotout";
        public static final String COL_LATEIN = "latein";
        public static final String COL_LATEOUT = "lateout";
    String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + TABLE_NAME + " (" +
                    COL_ID + " INTEGER PRIMARY KEY," +
                    COL_DATE + " TEXT," +
                    COL_PUNCHIN + " TEXT," +
                    COL_PUNCHOUT + " TEXT," +
                    COL_ONDUTY + " INTEGER," +
                    COL_FORGOTIN + " INTEGER," +
                    COL_FORGOTOUT + " INTEGER," +
                    COL_LATEIN + " INTEGER," +
                    COL_LATEOUT + " INTEGER);";
    String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + TABLE_NAME;
    // If you change the database schema, you must increment the database version.
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "PunchInTime.db";
    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(SQL_CREATE_ENTRIES);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // This database is only a cache for online data, so its upgrade policy is
        // to simply to discard the data and start over
        db.execSQL(SQL_DELETE_ENTRIES);
        System.out.println(SQL_CREATE_ENTRIES);
        onCreate(db);
    }
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }
}

为什么我会这样?在传递给Cursor之前,我似乎没有关闭数据库。

logcat的:

07-06 03:29:18.270 7848-7848/su.joel.punchintime E/AndroidRuntime: FATAL EXCEPTION: main
Process: su.joel.punchintime, PID: 7848
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteQuery: SELECT _id, date, punchin FROM punchlog ORDER BY date DESC
   at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
   at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:58)
   at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:151)
   at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:123)
   at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:236)
   at android.widget.CursorAdapter.getView(CursorAdapter.java:280)
   at android.widget.AbsListView.obtainView(AbsListView.java:2379)
   at android.widget.ListView.makeAndAddView(ListView.java:1970)
   at android.widget.ListView.fillDown(ListView.java:704)
   at android.widget.ListView.fillFromTop(ListView.java:765)
   at android.widget.ListView.layoutChildren(ListView.java:1744)
   at android.widget.AbsListView.onLayout(AbsListView.java:2171)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1197)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
   at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:434)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
   at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
   at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
   at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
   at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
   at com.android.internal.policy.DecorView.onLayout(DecorView.java:726)
   at android.view.View.layout(View.java:17745)
   at android.view.ViewGroup.layout(ViewGroup.java:5579)
   at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2380)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2094)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1280)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6432)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
   at android.view.Choreographer.doCallbacks(Choreographer.java:686)
   at android.view.Choreographer.doFrame(Choreographer.java:621)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
   at android.os.Handler.handleCallback(Handler.java:751)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6355)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

1 个答案:

答案 0 :(得分:0)

CursorAdapter取得传入的Cursor的所有权。自行调用close()会导致此错误。从此处删除cursor.close()

MyAdapter.changeCursor(cursor);
cursor.close();