尝试在游标关闭后访问它

7
我正在使用以下代码来删除一张图片。第一次操作时它能够正常工作,但是当我尝试捕获并删除一张图片时,会出现StaleDataException异常。
08-07 14:57:24.156: E/AndroidRuntime(789): java.lang.RuntimeException: Unable to               
       resume activity {com.example.cap_im/com.example.cap_im.MainActivity}:  
       android.database.StaleDataException: Attempted to access a cursor after it has been closed.

public void deleteImageFromGallery(String captureimageid) {
    Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

    getContentResolver().delete(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            BaseColumns._ID + "=?", new String[] { captureimageid });

    String[] projection = { MediaStore.Images.ImageColumns.SIZE,
            MediaStore.Images.ImageColumns.DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DATA, BaseColumns._ID, };

    Log.i("InfoLog", "on activityresult Uri u " + u.toString());

    try {
        if (u != null) {
            cursor = managedQuery(u, projection, null, null, null);
        }
        if ((cursor != null) && (cursor.moveToLast())) {

            int i = getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    BaseColumns._ID + "=" + cursor.getString(3),   null);
            Log.v(TAG, "Number of column deleted : " + i);
        }
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

那么你的问题是什么?错误信息已经很明显地解释了。 - tyczj
第二次我无法删除图片。 - Dilshi
错误指向哪一行? - thegrinner
光标声明在哪里?也许你可以这样做:Cursor cursor = managedQuery... - d'alar'cop
我声明为全局变量。 - Dilshi
5个回答

43

函数managedQuery()已经被废弃,请使用getContentResolver().query()

参数相同。


仍然无法在Oreo版本中运行。请帮帮我。 - Anand Savjani
使用getContentResolver编写时,如何避免参数错误?游标cursor = getContentResolver().query(queryUri, projection, selection, null, null); - Jarin Rocks

8
在你的 finally 块中,你关闭了游标,但没有将其设置为 null。因此,下次调用你的方法时,cursor.getString(3) 会失败,因为游标已被关闭。
解决方法:在你的 finally 块中将 cursor 设置为 null
正确的解决方法是:不要使用实例变量来存储你的 cursor,而是在方法中使用一个局部变量。

2

我曾遇到过类似的问题。在我的情况下,代码本身没问题,但是我使用了已被弃用的方法“managedQuery”,而没有使用Tom Lin建议的方法。

public String getPath(Uri uri) {
    if (uri == null) {
        return null;
    }
    String result = null;

    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

    // deprecated:
    // Cursor cursor = managedQuery(uri, projection, null, null, null);

    if (cursor != null) {

        int columnIndex = 0;
        try {
            columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            result = cursor.getString(columnIndex);
        } catch (IllegalArgumentException e) {
            Log.e("While getting path for file", e);
        } finally {
            try {
                if (!cursor.isClosed()) {
                    cursor.close();
                }
                cursor = null;
            } catch (Exception e) {
                Log.e("While closing cursor", e);
            }
        }
    }
    return result;
}

如果我使用已弃用的方法,如果省略 finally,它仍然有效。在文档中也明确说明,在使用此方法时不应关闭游标。

1

一定要使用getContentResolver().query()代替managedQuery()来确保代码正常运行。因为managedQuery()已经过时。这对我非常有效。


0

另外不要使用managedQuery(),它已经被弃用。

移除这个:

protected SQLiteDatabase database;

并将其设为本地

基本上有两种方法同时执行,其中一种方法调用了database.close(),而第二种方法仍在访问数据,因此会出现异常

使用这个:

   public class db {

    DataBaseHelper dbHelper;
    Context mContext;


    public db(Context context) {
        this.mContext = context;
    }

    public db open() throws SQLException {
        dbHelper = new DataBaseHelper(mContext);
        return this;
    }


    public void close() {
        dbHelper.close();
    }

    public void insertdb( int id,String ph_num, String call_type, String calldate, String call_duration, String upload_status) {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DataBaseHelper.id,id);
        values.put(DataBaseHelper.phone_number, ph_num);
        values.put(DataBaseHelper.call_type, call_type);
        values.put(DataBaseHelper.call_date, calldate);
        values.put(DataBaseHelper.call_duration, call_duration);
        values.put(DataBaseHelper.upload_status, upload_status);
        database.insert(DataBaseHelper.table_name, null, values);
        database.close();
        // Log.d("Database helper", "values inserted");
    }


    public ArrayList<HashMap<String, String>> getAllUsers() {
        ArrayList<HashMap<String, String>> wordList;
        wordList = new ArrayList<HashMap<String, String>>();
        String selectQuery = "SELECT  * FROM call_logtable";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        if (cursor.moveToFirst()) {
            do {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("id", cursor.getString(0));
                map.put("phone_number", cursor.getString(1));
                map.put("call_type", cursor.getString(2));
                map.put("call_date", cursor.getString(3));
                map.put("call_duration", cursor.getString(4));
                wordList.add(map);
            } while (cursor.moveToNext());
        }
        cursor.close(); // just added
        database.close();
        return wordList;
    }

    /**
     * Compose JSON out of SQLite records
     * @return
     */
    public String composeJSONfromSQLite(){
        ArrayList<HashMap<String, String>> wordList;
        wordList = new ArrayList<HashMap<String, String>>();
        String selectQuery = "SELECT  * FROM call_logtable where upload_status = '"+"no"+"'";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        if (cursor.moveToFirst()) {
            do {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put("id", cursor.getString(0));
                map.put("phone_number", cursor.getString(1));
                map.put("call_type", cursor.getString(2));
                map.put("call_date", cursor.getString(3));
                map.put("call_duration", cursor.getString(4));
                wordList.add(map);
            } while (cursor.moveToNext());
        }
        cursor.close(); // just added
        database.close();
        Gson gson = new GsonBuilder().create();
        //Use GSON to serialize Array List to JSON
        return gson.toJson(wordList);
    }


    public int dbSyncCount(){
        int count = 0;
        String selectQuery = "SELECT  * FROM call_logtable where upload_status = '"+"no"+"'";
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);
        count = cursor.getCount();
        cursor.close(); // just added
        database.close();
        return count;
    }


    public void updateSyncStatus(String id, String status){
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        String updateQuery = "Update call_logtable set upload_status = '"+ status +"' where id="+"'"+ id +"'";
        Log.d("query", updateQuery);
        database.execSQL(updateQuery);
        database.close();
    }

    public Cursor getinformation()
    {
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        String[] columns={DataBaseHelper.phone_number,DataBaseHelper.call_type,DataBaseHelper.call_date,DataBaseHelper.call_duration,DataBaseHelper.upload_status};
        return database.query(DataBaseHelper.table_name,columns,null,null,null,null,null);
    }

    public void delete()
    {
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        // String[] columns={DataBaseHelper.phone_number,DataBaseHelper.call_type,DataBaseHelper.call_date,DataBaseHelper.call_duration};
        database.delete(DataBaseHelper.table_name, null, null);
    }


    StringBuffer readSpecificfrom_db(String type)
    {
        String ph_number=null;
        String call_type=null;
        String call_date=null;
        String call_duration=null;
        String upload_status=null;
        StringBuffer sb = new StringBuffer();
        //sb.append("Call Log :");
        Cursor cursor_object=getinformation();
        cursor_object.moveToFirst();
        do {
            if((cursor_object.getString(1)).equals(type)) {
                ph_number = cursor_object.getString(0);
                call_type = cursor_object.getString(1);
                call_date = cursor_object.getString(2);
                call_duration = cursor_object.getString(3);
                if(type=="Missed") {
                    sb.append("\nPhone Number:--- " + ph_number +
                                    " \nCall Type:--- " + call_type +
                                    " \nCall Date:--- " + call_date
                            //   + " \nCall duration in sec :--- " + call_duration
                    );
                    sb.append("\n----------------------------------");
                }
                else
                {
                    sb.append("\nPhone Number:--- " + ph_number +
                            " \nCall Type:--- " + call_type +
                            " \nCall Date:--- " + call_date
                            + " \nCall duration in sec :--- " + call_duration);
                    sb.append("\n----------------------------------");
                }
            }
        }while(cursor_object.moveToNext());
        cursor_object.close(); // just added
        return sb;

    }

    StringBuffer readfrom_db()
    {
        String ph_number=null;
        String call_type=null;
        String call_date=null;
        String call_duration=null;
        String upload_status;
        //  int id=0;
        StringBuffer sb = new StringBuffer();
        // sb.append("Call Log :");
        Cursor cursor_object=getinformation();
        cursor_object.moveToFirst();
        do {
            ph_number=cursor_object.getString(0);
            call_type=cursor_object.getString(1);
            call_date=cursor_object.getString(2);
            call_duration=cursor_object.getString(3);
            sb.append("\nPhone Number:--- " + ph_number +
                    " \nCall Type:--- " + call_type +
                    " \nCall Date:--- " + call_date
                    + " \nCall duration in sec :--- " + call_duration);
            sb.append("\n----------------------------------");

        } while(cursor_object.moveToNext());
        cursor_object.close(); // just added
        return sb;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接