错误:尝试重新打开已关闭的对象:SQLiteQuery

时间:2015-07-11 16:19:50

标签: android sqlite cursor android-adapter

我已经阅读了与此相似的其他问题,但无法解决此问题。

我正在尝试查询数据库并使用结果填充列表视图。正如您在代码中看到的,我已经以几种不同的方式完成了这项工作,即。返回数组列表等。使用此特定列表,我试图返回一个光标,然后将其发送到自定义适配器。我收到以下错误:

07-11 10:55:27.192  30405-30405/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.bkane56.practice.practiceapp, PID: 30405
java.lang.IllegalStateException: attempt to re-open an already-closed  object: SQLiteQuery: SELECT stop_name, stop_lat, stop_lon, _id FROM stops
        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:152)
        at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:124)
        at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:214)
        at android.widget.CursorAdapter.getView(CursorAdapter.java:245)
        at android.widget.AbsListView.obtainView(AbsListView.java:2347)
        at android.widget.ListView.measureHeightOfChildren(ListView.java:1270)
        at android.widget.ListView.onMeasure(ListView.java:1182)
        at android.view.View.measure(View.java:17547)
        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:727)
        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:463)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1436)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:722)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:613)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5535)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:436)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2615)
        at android.view.View.measure(View.java:17547)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2015)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1173)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1379)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
        at android.view.Choreographer.doCallbacks(Choreographer.java:580)
        at android.view.Choreographer.doFrame(Choreographer.java:550)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5257)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

这是我的activty.class:

package com.bkane56.practice.practiceapp;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;


public class NavigateActivity extends Activity {

    private MetroLinkDatabaseHelper myHelper =
            MetroLinkDatabaseHelper.getInstance(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_navigate);

        populateLocationLIst();

    }

    private void openDB() {

        myHelper.open();
    }

    private void closeDB() {
        myHelper.close();
    }

    public void populateLocationLIst( ) {


        Cursor cursor = myHelper.getAllLcations();
        ListView lvItems = (ListView) findViewById(R.id.lvLocations);
        LocationCursorAdaptor locationAdaptor = new LocationCursorAdaptor(this, cursor);
        lvItems.setAdapter(locationAdaptor);

        cursor.close();
    }

//    ....Menu methods left out of this question but present in class.
}

My Helper.class如下:

package com.bkane56.practice.practiceapp;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;


public class MetroLinkDatabaseHelper extends SQLiteOpenHelper {

    private Context mycontext;
    private String stopName;
    private String sqlQueryTimes;
    private static MetroLinkDatabaseHelper myInstance;

    private static String DB_PATH = "data/data/com.bkane56.practice.practiceapp/databases/";
    private static String DB_NAME = "metrolink2.db";
    public static SQLiteDatabase myDataBase;

    public static synchronized MetroLinkDatabaseHelper getInstance(Context context) {

//        Using a singleton to minmize the chance of opening multiple
//        decreasing any chance of memory leak
        if(myInstance == null) {
            myInstance = new MetroLinkDatabaseHelper(context);
        }
        return myInstance;
    }


    private MetroLinkDatabaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.mycontext = context;
        boolean dbexist = checkdatabase();
        if (dbexist) {
        } else {
            System.out.println("Database doesn't exist");
            try {
                createdatabase();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    //      Create (copy the original in assets) if not exist using copydatabase
    public void createdatabase() throws IOException {
        boolean dbexist = checkdatabase();
        if (dbexist) {
        } else {
            this.getReadableDatabase();
            try {
                copydatabase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    //     Check if the Android database has been created from attached database
    private boolean checkdatabase() {
        boolean checkdb = false;
        try {
            String myPath = DB_PATH + DB_NAME;
            File dbfile = new File(myPath);
            checkdb = dbfile.exists();
            if (!checkdb) {
                System.out.println("THE DATA BASE DOES NOT EXIST");
            }
        } catch (SQLiteException e) {
            System.out.println("Database doesn't exist");
        }

        return checkdb;
    }

    //    copies the data from the metroLink db in assets to data/data....metrolink.db
    public void copydatabase() throws IOException {

        // Open your local db as the input stream
        InputStream myinput = mycontext.getAssets().open(DB_NAME);
        String outfilename = DB_PATH + DB_NAME;

        // Open the empty db as the output stream
        OutputStream myoutput = new FileOutputStream(outfilename);

        // buffered reader to write new database
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myinput.read(buffer)) > 0) {
            myoutput.write(buffer, 0, length);
        }
        // Close the streams
        myoutput.flush();
        myoutput.close();
        myinput.close();
    }

    public static SQLiteDatabase open() {
        // Open the database
        String mypath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(mypath, null,
                SQLiteDatabase.OPEN_READONLY);
        return myDataBase;
    }

    public synchronized void close() {
        super.close();
        myDataBase.close();

    }

    public void delete() {
        //Delete Existing Database
        File mypath = new File(DB_PATH + DB_NAME);
        myDataBase.close();
        System.out.println("DELETING THE EXISTING DATABASE");
        myDataBase.deleteDatabase(mypath);
    }

    //    returns a list of all the stops sorted by longitude west to east
    public List<String> getAllStops() {

        final String TABLE = "stops";
        final String[] COLUMN = new String[]{"stop_name"};
        final String ORDER_BY = "stop_name";
        String myPath = DB_PATH + DB_NAME;
        List<String> stopList = new ArrayList<String>();

//        open data base
        open();

        Cursor c = myDataBase.query(TABLE, COLUMN, null, null, null, null, ORDER_BY, null);
//            Cursor c = myDataBase.rawQuery("select stop_name as _id from stops", null);

        if (c.moveToFirst()) {
            do {
                stopList.add(c.getString(0));
            }
            while (c.moveToNext());
            if (c != null && !c.isClosed()) {
                c.close();
            }

        }
        myDataBase.close();
        return stopList;

    }

//    Returns a cursor with stop_name, stop_lat, stop_lon, _id from metrolink2.db
    public Cursor getAllLcations() {

//        populate list stopLon, list stopLat, list stopName
        List<String> stopLL = new ArrayList<>();
        List<List<String>> nameLatLong = new ArrayList<>();

//        open database
        open();

        Cursor c = myDataBase.rawQuery("SELECT stop_name, stop_lat, stop_lon, _id " +
                "FROM stops", null);
        if (c.moveToFirst()) {

            do {

                stopLL.add(c.getString(0));
                stopLL.add(c.getString(1));
                stopLL.add(c.getString(2));
                stopLL.add(c.getString(3));
                nameLatLong.add(stopLL);
                stopLL.clear();
            }
            while (c.moveToNext());
//            if (c != null && !c.isClosed()) {
//                c.close();
//           }
        }
        myDataBase.close();
        return c;
    }

    //    gets next 3 stop times
    public List<String> getStopTimes(String sqlQueryTimes) {
        this.sqlQueryTimes = sqlQueryTimes;

        List<String> stopTime = new ArrayList<String>();
        String myPath = DB_PATH + DB_NAME;

//        open database
        open();

        Cursor c = myDataBase.rawQuery(sqlQueryTimes, null);

        if (c.moveToFirst()) {
            do {
                stopTime.add(c.getString(0));
            }
            while (c.moveToNext());
            if (c != null && !c.isClosed()) {
                c.close();
            }

        }
        myDataBase.close();
        return stopTime;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

最后我的adapter.class是这样的:

package com.bkane56.practice.practiceapp;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.TextView;

public class LocationCursorAdaptor extends CursorAdapter {

    public LocationCursorAdaptor(Context context, Cursor cursor) {
        super(context, cursor, 0);
    }

    // The newView method is used to inflate and return a new view
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.lv_navigation, parent, false);
    }

    // Binds the data from db to the text views in list view
    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        TextView tvStopName = (TextView) view.findViewById(R.id.tvStopName);
        TextView tvLat = (TextView) view.findViewById(R.id.tvLatitude);
        TextView tvLon = (TextView) view.findViewById(R.id.tvLongitude);

        String stopName = cursor.getString(cursor.getColumnIndexOrThrow("stop_name"));
        String  stopLat = cursor.getString(cursor.getColumnIndexOrThrow("stop_lat"));
        String  stopLon = cursor.getString(cursor.getColumnIndexOrThrow("stop_lon"));
        String _id = cursor.getString(cursor.getColumnIndexOrThrow("_id"));

        // Set textview with text from cursor
        tvStopName.setText(stopName);
        tvLat.setText(stopLat);
        tvLon.setText(stopLon);
    }
}

getAllStops()方法和getStopTimes()方法工作正常。它们与getAllLocations()方法的活动不同。

非常感谢任何帮助。

如果您需要更多信息,请与我们联系。

0 个答案:

没有答案