【问题标题】:Android "attempted to access a cursor after it has been closed"Android“试图在光标关闭后访问它”
【发布时间】:2013-02-17 12:25:56
【问题描述】:

我正在尝试调整 HelloGridView 示例,以便我可以显示存储在 SD 上的图像的图像缩略图,而不是 res/drawable 中的图像。这个想法是首先在 ImageView.initialize() 函数中创建一个包含图像的列表,然后使用它几乎与示例中一样。

我的光标有问题,首先我尝试在 Imageview.initialize() 函数中将它设为私有(它只是被注释掉了,所以你可以看到它在哪里),因为在我看来它是仅在此处使用,但随后出现错误“尝试在游标关闭后访问游标”。在 onCreate() 函数的行

gridview.setAdapter(imageAdapter);

所以这条线显然以某种方式使用它。下一次尝试是将光标设置为“全局”并在该行之后关闭它,但我得到了同样的错误,但现在当我离开 onCreate() 时。 这就是现在的代码,我不知道该怎么做。另外,如果您发现任何其他看起来很奇怪的东西,请告诉我,因为我是 android 和 java 的新手。

package se.mmarks.hellogridview;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private Cursor imagecursor;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView gridview = (GridView) findViewById(R.id.gridview);
        ImageAdapter imageAdapter = new ImageAdapter(this, imagecursor);
        imagecursor = imageAdapter.initialize();
        gridview.setAdapter(imageAdapter);
        /* setAdapter needs the cursor,
         * this is why it is closed here and not in ImageAdapter.initialize()
        */
        imagecursor.close();

        gridview.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            Toast.makeText(MainActivity.this, "" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }
}



class ImageAdapter extends BaseAdapter {
    private ArrayList<ImageView> images = new ArrayList<ImageView>();
    Cursor imagecursor = null;


    private Context mContext;

    public ImageAdapter(Context c, Cursor cursor) {
        mContext = c;
        imagecursor = cursor;
    }

    public Cursor initialize() {
        final String[] columns = { MediaStore.Images.Thumbnails._ID };
        imagecursor = null;
        try {
            imagecursor = mContext.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, null);
        } catch(Exception e) {
            e.printStackTrace();
        }

        if(imagecursor != null){
            int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Thumbnails._ID);
            int count = imagecursor.getCount();
            for (int i = 0; i < count; i++) {
                imagecursor.moveToPosition(i);
                int id = imagecursor.getInt(image_column_index);
                ImageView imageItem = new ImageView(mContext);
                imageItem.setId(id);
                imageItem.setImageBitmap(
                    MediaStore.Images.Thumbnails.getThumbnail(mContext.getContentResolver(), id,
                    MediaStore.Images.Thumbnails.MICRO_KIND, null));
                images.add(imageItem);
            }
            //imagecursor.close();
        }
        return imagecursor;
    }

    @Override
    public int getCount() {
        return imagecursor.getCount();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = images.get(position);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }
        return imageView;
    }
}

【问题讨论】:

    标签: android adapter android-imageview android-gridview android-cursor


    【解决方案1】:

    Android“试图在光标关闭后访问它”

    当您工作/访问Cursor 中的数据时,需要将其打开!

    一般建议在onStop()onDestroy()方法中关闭Activity生命周期方法中的所有datasourcescursors

    基本示例:

    public void onDestroy() {
       super.onDestroy();
       if (cursor != null) {
          c.close();
       }
       if (db != null) {
          db.close();
       }
    }
    

    【讨论】:

    • 谢谢 sajmon_d!我添加了 onStop() 函数并将 imagecursor.close() 移到那里,现在它可以工作了! :)
    【解决方案2】:

    因为我没有足够的声誉来发表评论......

    我必须补充一个事实,即使正确答案说您可以关闭光标onDestroy(),这不是您应该做的事情。

    onDestroy 方法不保证会调用 Cursor.close(),因为 android 本身不保证最终会调用 onDestroy。

    来自文档:

    onDestroy() = 您在活动之前收到的最后一个电话是 被摧毁。这可能是因为活动正在结束 (有人叫finish()就可以了,或者因为系统暂时 销毁该活动实例以节省空间。你可以 用 isFinishing() 方法区分这两种情况。

    【讨论】:

      猜你喜欢
      • 2018-08-12
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多