"确保Cursor在从它访问数据之前被初始化"的Android

时间:2016-08-25 03:52:19

标签: android sqlite blob

我理解这个问题之前已被多次询问,但在这种情况下它是不同的,因为错误只发生在尝试将图像保存到数据库而其他问题不处理图像时。如果有,请通过链接发表评论。

首先我只发布我认为必要的代码,所以如果我错过了一些代码或任何内容,请告诉我。我有一个笔记记录应用程序,它存储2个不同的EditText字段作为笔记标题和笔记正文。这很好。我尝试添加从SQLite数据库添加,存储和检索图像的功能。这是我的EditNoteActivity类中的代码,它在" store"用户完成编辑注释后按下后退按钮转到MainActivity类。

private void updateNote(String noteText, String titleText) {
        Log.d("Img", "updateNote");
        ContentValues values = new ContentValues();
        ImageView img = (ImageView) findViewById(R.id.imageView);

        byte[] data;
        if (img.getDrawable() != null) {
            Log.d("Img", "updateNote ----- image here");
            Bitmap bitmap = ((BitmapDrawable)img.getDrawable()).getBitmap();
//        data = getBitmapAsByteArray(bitmap);
            data = DbBitmapUtility.getBytes(bitmap);
        } else {
            Log.d("Img", "updateNote ----- image not here");
            data = null;
        }
        values.put(DBOpenHelper.NOTE_IMAGE, data);
        values.put(DBOpenHelper.NOTE_BODY, noteText);
        values.put(DBOpenHelper.NOTE_TITLE, titleText);
        // reusing noteFilter value to make sure you're only updating 1 selected row
        getContentResolver().update(NoteProvider.CONTENT_URI, values, noteFilter, null);
        Toast.makeText(this, R.string.note_updated, Toast.LENGTH_SHORT).show();
        setResult(RESULT_OK);   // send message to MainActivity saying something has changed, update content in list
    }

如果我没有将图像添加到ImageView,那么我可以保存笔记没问题。但是,如果我添加一个图像,然后尝试返回MainActivity,程序会崩溃,如下所示:

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    cursorAdapter.swapCursor(data);    // crashes here
}

它也会在类声明中崩溃:

public class MainActivity extends AppCompatActivity

由于我经常使用Log.d,所以它在logcat中说如下:

  

updateNote   updateNote ----- image here

如果您按照updateNote方法中的代码应该这样做。这是DbBitmapUtility类中的getBytes方法,我用它来获取一个字节数组,用于将图像存储为BLOB:

// convert from bitmap to byte array
public static byte[] getBytes(Bitmap bitmap) {
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 0, stream);
    return stream.toByteArray();
}

最后这是我的数据库设置:

public static final String TABLE_NOTES = "notes";
public static final String NOTE_ID = "_id";
public static final String NOTE_TITLE = "noteTitle";
public static final String NOTE_BODY = "noteBody";
public static final String NOTE_IMAGE = "noteImage";
public static final String NOTE_CREATED = "noteCreated";

public static final String[] ALL_COLUMNS =
        {NOTE_ID, NOTE_TITLE, NOTE_BODY, NOTE_IMAGE, NOTE_CREATED};
// SQL to create table
private static final String TABLE_CREATE =
        "CREATE TABLE " + TABLE_NOTES + " (" +
                NOTE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                NOTE_TITLE + " TEXT, " +
                NOTE_BODY + " TEXT, " +
                NOTE_IMAGE + " BLOB, " +
                NOTE_CREATED + " TEXT default CURRENT_TIMESTAMP" +
                ")";

以下是错误:

  

E / AndroidRuntime:致命异常:主要                                                                               处理:com.beauty.comp_eng.mynote,PID:16435                                                                               java.lang.IllegalStateException:无法读取第0行,第0列   CursorWindow。确保之前正确初始化了Cursor   从中访问数据。                                                                                   在android.database.CursorWindow.nativeGetLong(本机方法)                                                                                   在android.database.CursorWindow.getLong(CursorWindow.java:511)                                                                                   在   android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)                                                                                   在android.database.CursorWrapper.getLong(CursorWrapper.java:127)                                                                                   在android.widget.CursorAdapter.getItemId(CursorAdapter.java:259)                                                                                   在android.widget.AdapterView.rememberSyncState(AdapterView.java:1243)                                                                                   在   android.widget.AdapterView $ AdapterDataSetObserver.onChanged(AdapterView.java:830)                                                                                   在   android.widget.AbsListView $ AdapterDataSetObserver.onChanged(AbsListView.java:6470)                                                                                   在   android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)                                                                                   在   android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)                                                                                   在android.widget.CursorAdapter.swapCursor(CursorAdapter.java:381)                                                                                   在   com.beauty.comp_eng.mynote.MainActivity.onLoadFinished(MainActivity.java:200)                                                                                   在   com.beauty.comp_eng.mynote.MainActivity.onLoadFinished(MainActivity.java:25)                                                                                   在   android.support.v4.app.LoaderManagerImpl $ LoaderInfo.callOnLoadFinished(LoaderManager.java:479)                                                                                   在   android.support.v4.app.LoaderManagerImpl $ LoaderInfo.onLoadComplete(LoaderManager.java:447)                                                                                   在android.support.v4.content.Loader.deliverResult(Loader.java:126)                                                                                   在   android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:105)                                                                                   在   android.support.v4.content.CursorLoader.deliverResult(CursorLoader.java:37)                                                                                   在   android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:249)                                                                                   在   android.support.v4.content.AsyncTaskLoader $ LoadTask.onPostExecute(AsyncTaskLoader.java:77)                                                                                   在   android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:466)                                                                                   在   android.support.v4.content.ModernAsyncTask.access $ 400(ModernAsyncTask.java:48)                                                                                   在   android.support.v4.content.ModernAsyncTask $ InternalHandler.handleMessage(ModernAsyncTask.java:483)                                                                                   在android.os.Handler.dispatchMessage(Handler.java:102)                                                                                   在android.os.Looper.loop(Looper.java:148)                                                                                   在android.app.ActivityThread.main(ActivityThread.java:5525)                                                                                   at java.lang.reflect.Method.invoke(Native Method)                                                                                   在   com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:730)                                                                                   在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

我以为我正在正确地存储图像,因为我发现它们在许多其他stackoverflow答案中的表现方式,但它不起作用。我注意到它说了

  

无法从CursorWindow读取第0行,第0列。在从中访问数据之前,请确保Cursor已正确初始化。

如果数据库中没有存储图像的普通笔记,为什么没有返回记录?

1 个答案:

答案 0 :(得分:5)

Android sqlite游标有一个固定大小的内部缓冲区,名为CursorWindow,在大多数配置下都是2MB。尝试在游标行中移动更多数据将不起作用。

不要将图像数据或任何其他大数据存储在Android sqlite数据库中。而是将图像存储到文件系统并将文件路径存储在数据库中。