简体   繁体   English

Android ContentProvider SQLite:SQLiteMisuseException

[英]Android ContentProvider SQLite : SQLiteMisuseException

I have a simple ContentProvider following the step from vogella.com with some changes because I'm using android-support-v4.jar I have a simple App 我有一个简单的ContentProvider,它遵循了vogella.com的步骤进行了一些更改,因为我使用的是android-support-v4.jar我有一个简单的App

在此处输入图片说明

Here i have three buttons and one ListFragment all use custom ContentProvider the i'm looking for problems but when i try to pulse faster the buttons sometimes i get a SQLiteMisuseException the docs tell 在这里,我有三个按钮,一个ListFragment都使用自定义ContentProvider,我在寻找问题,但是当我尝试加快脉冲速度时,有时我会收到一个SQLiteMisuseException文档告诉

This error can occur if the application creates a SQLiteStatement object and allows multiple threads in the application use it at the same time 如果应用程序创建一个SQLiteStatement对象并允许应用程序中的多个线程同时使用它,则会发生此错误。

but i dont have many threads (At least I think). 但我没有很多线程(至少我认为)。

Update : sometimes the app stop working the UI work but does not respond 更新 :有时应用程序停止UI工作,但没有响应

Update 2 : Can be a problem with the speed response of the device i'm testing in a Galaxy ACE (with the error) and a Galaxy SIII works fine 更新2 :我正在Galaxy ACE中测试的设备的速度响应可能有问题(有错误),并且Galaxy SIII可以正常工作


MainActivity.java MainActivity.java

package com.example.providertest;

import java.util.Random;

import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.Menu;
import android.view.View;

public class MainActivity extends FragmentActivity {

    private List mLista;

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

        mLista = (List) getSupportFragmentManager().findFragmentById(R.id.la_lista);

        getSupportLoaderManager().initLoader(0, null, mLista);
    }

    public static class List extends ListFragment implements LoaderCallbacks<Cursor>
    {
        private SimpleCursorAdapter mAdapter;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);

            final String[] from = new String[] { CommentHelper.COLUMN_COMMENT };
            final int[] to = new int[] {android.R.id.text1 };

            mAdapter = new SimpleCursorAdapter(
                    getActivity().getApplicationContext(), R.layout.lista_item, null, from, to, 0);
            setListAdapter(mAdapter);

        }

        @Override
        public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
            final CursorLoader loader = new CursorLoader(
                    getActivity().getApplicationContext(),
                    CommentProvider.CONTENT_URI,
                    CommentDataSource.sAllColumns, null, null, null);

            return loader;
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
            mAdapter.swapCursor(cursor);
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {
            mAdapter.swapCursor(null);
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void buttonPressed(View view)
    {
        final String[] comments = {"Excelente", "Bueno", "Que mas da", "Malo"};
        Comment comment = null;

        switch (view.getId()) {
        case R.id.add:
            comment = new Comment();
            final int nextInt = new Random().nextInt(comments.length);
            comment.setComment(comments[nextInt]);
            getContentResolver().insert(CommentProvider.CONTENT_URI, CommentDataSource.toValues(comment));
            break;
        case R.id.delete_first:
            deleteOne("ASC");
            break;
        case R.id.delete_last:
            deleteOne("DESC");
            break;
        }

    }

    private void deleteOne(String order) {
        final Cursor c = getContentResolver().query(CommentProvider.CONTENT_URI, null, null, null, "_ID " + order + " LIMIT 1");
        c.moveToFirst();
        if (!c.isAfterLast()) {
            final String _id = c.getString(c.getColumnIndexOrThrow(CommentHelper.COLUMN_ID));
            getContentResolver().delete(CommentProvider.CONTENT_URI, "_ID = ?", new String[] { _id });
        }
        c.close();
    }
}

activity_main.xml activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/add"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="@string/add_new"
            android:onClick="buttonPressed" />

        <Button
            android:id="@+id/delete_first"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:text="@string/delete_first"
            android:onClick="buttonPressed" />

        <Button
            android:id="@+id/delete_last"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:onClick="buttonPressed"
            android:text="@string/delete_last" />
    </LinearLayout>

    <fragment
        android:id="@+id/la_lista"
        class="com.example.providertest.MainActivity$List"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Data 数据

CommentHelper.java CommentHelper.java

package com.example.providertest;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;

public class CommentHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "comments.db";
    private static final int DATABASE_VERSION = 1;
    public static final String TABLE_NAME = "comments";

    public static final String COLUMN_ID = BaseColumns._ID;
    public static final String COLUMN_COMMENT = "comment";

    private static final String DATABASE_CREATE = "CREATE TABLE " +
            TABLE_NAME + "(" +
                    COLUMN_ID + " INTEGER PRIMARY KEY, " +
                    COLUMN_COMMENT + " TEXT NOT NULL" +
                    ");";
    private static final String DATABASE_DROP = "DROP TABLE IF EXISTS " + TABLE_NAME;


    public CommentHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DATABASE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(DATABASE_DROP);
        onCreate(db);
    }
}

CommentDataSource.java CommentDataSource.java

package com.example.providertest;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class CommentDataSource {

    private final CommentHelper mHelper;
    public static String[] sAllColumns = {CommentHelper.COLUMN_ID, CommentHelper.COLUMN_COMMENT};

    public CommentDataSource(Context context) {
        mHelper = new CommentHelper(context);
    }

    public SQLiteDatabase getDatabase()
    {
        return getDatabase(false);
    }

    public SQLiteDatabase getDatabase(boolean writable)
    {
        return writable ? mHelper.getWritableDatabase() : mHelper.getReadableDatabase();
    }

    public Comment Save(Comment comment)
    {
        final ContentValues values = toValues(comment);
        final long insertId = insert(values);
        comment.setId(insertId);
        return comment;
    }

    public long insert(ContentValues values)
    {
        final SQLiteDatabase db = mHelper.getWritableDatabase();
        try {
            final long insertId = db.insert(CommentHelper.TABLE_NAME, null, values);
            return insertId;
        } finally {
            db.close();
        }
    }

    public int update(ContentValues values, String selection, String[] selectionArgs)
    {
        final SQLiteDatabase db = mHelper.getWritableDatabase();

        try {
            final int rowsUpdated = db.update(CommentHelper.TABLE_NAME, values, selection, selectionArgs);
            return rowsUpdated;
        } finally {
            db.close();
        }
    }

    public int update(long id, ContentValues values)
    {
        final String whereClause = String.format("%s = %s", CommentHelper.COLUMN_ID, id);
        return update(values, whereClause, null);
    }

    public int delete(String selection, String[] selectionArgs)
    {
        final SQLiteDatabase db = mHelper.getWritableDatabase();

        try {
            final int rowsDeleted = db.delete(CommentHelper.TABLE_NAME, selection, selectionArgs);
            return rowsDeleted;
        } finally {
            db.close();
        }
    }

    public int delete(long id)
    {
        final SQLiteDatabase db = mHelper.getWritableDatabase();
        final String whereClause = String.format("%s = %s", CommentHelper.COLUMN_ID, id);

        try {
            final int rowsDeleted = db.delete(CommentHelper.TABLE_NAME, whereClause, null);
            return rowsDeleted;
        } finally {
            db.close();
        }
    }

    public int delete(Comment comment)
    {
        return delete(comment.getId());
    }

    public List<Comment> findAll()
    {
        final List<Comment> comments = new ArrayList<Comment>();
        final SQLiteDatabase db = mHelper.getReadableDatabase();
        final Cursor cursor = db.query(CommentHelper.TABLE_NAME, sAllColumns, null, null, null, null, null);

        try {
            cursor.moveToFirst();
            while(!cursor.isAfterLast()) {
                comments.add(fromCursor(cursor));
                cursor.moveToNext();
            }

            return comments;
        } finally {
            cursor.close();
            db.close();
        }
    }

    public Comment fromCursor(Cursor cursor)
    {
        final Comment comment = new Comment();
        comment.setId(cursor.getLong(0));
        comment.setComment(cursor.getString(1));

        return comment;
    }


    public static ContentValues toValues(Comment comment)
    {
        final ContentValues values = new ContentValues();

        // Si el valor ho se ha definido es mejor no incluirlo
        // Evita problemas con el AUTOINCREMENT de SQLite
        if(comment.getId() > 0) {
            values.put(CommentHelper.COLUMN_ID, comment.getId());
        }

        values.put(CommentHelper.COLUMN_COMMENT, comment.getComment());

        return values;
    }
}

CommentProvider.java CommentProvider.java

package com.example.providertest;

import java.util.Arrays;
import java.util.HashSet;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class CommentProvider extends ContentProvider {

    private CommentDataSource mDataSource;

    private static final String AUTHORITY = "com.example.comments";
    private static final int COMMENT = 10;
    private static final int COMMENT_ID = 20;

    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/comments");

    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sUriMatcher.addURI(AUTHORITY, "comments", COMMENT);
        sUriMatcher.addURI(AUTHORITY, "comments/#", COMMENT_ID);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int rowsDeleted = 0;

        switch (sUriMatcher.match(uri)) {
        case COMMENT:
            rowsDeleted = mDataSource.delete(selection, selectionArgs);
            break;
        case COMMENT_ID:
            final long id = Long.parseLong(uri.getLastPathSegment());
            if(TextUtils.isEmpty(uri.getLastPathSegment())) {
                rowsDeleted = mDataSource.delete(id);
            } else {
                selection = CommentHelper.COLUMN_ID + " = " + id + " and " + selection;
                rowsDeleted = mDataSource.delete(selection, selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknow URI: " + uri);
        }

        getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long insertId = 0;

        switch (sUriMatcher.match(uri)) {
        case COMMENT:
            insertId = mDataSource.insert(values);
            break;
        }
        getContext().getContentResolver().notifyChange(uri, null);

        return Uri.parse("comments/" + insertId);
    }

    @Override
    public boolean onCreate() {
        mDataSource = new CommentDataSource(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {

        final SQLiteQueryBuilder builder = new SQLiteQueryBuilder();

        checkColumns(projection);

        builder.setTables(CommentHelper.TABLE_NAME);

        switch (sUriMatcher.match(uri)) {
        case COMMENT_ID:
            builder.appendWhere(String.format("%s = %s", CommentHelper.COLUMN_ID, uri.getLastPathSegment()));
            break;
        case COMMENT:
            break;
        default:
            throw new IllegalArgumentException("Unknow URI: " + uri);
        }

        final SQLiteDatabase db = mDataSource.getDatabase();
        final Cursor cursor = builder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    private void checkColumns(String[] projection) {
        if (projection != null) {
            final HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
            final HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(CommentDataSource.sAllColumns));
            if (!availableColumns.containsAll(requestedColumns)) {
                throw new IllegalArgumentException("Unknow columns in projection");
            }
        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        int rowsUpdated = 0;

        switch (sUriMatcher.match(uri)) {
        case COMMENT_ID:
            final long id = Long.parseLong(uri.getLastPathSegment());
            if(TextUtils.isEmpty(uri.getLastPathSegment())) {
                rowsUpdated = mDataSource.update(id, values);
                break;
            } else {
                selection = CommentHelper.COLUMN_ID + " = " + id + " and " + selection;
            }
        case COMMENT:
            rowsUpdated = mDataSource.update(values, selection, selectionArgs);
            break;
        default:
            throw new IllegalArgumentException("Unknow URI: " + uri);
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return rowsUpdated;
    }

}

Error 错误

05-04 09:45:48.031: D/dalvikvm(19873): GC_CONCURRENT freed 327K, 48% free 3114K/5895K, external 1073K/1585K, paused 4ms+7ms
05-04 09:45:54.421: W/dalvikvm(19873): threadid=11: thread exiting with uncaught exception (group=0x40018578)
05-04 09:45:54.554: E/AndroidRuntime(19873): FATAL EXCEPTION: ModernAsyncTask #3
05-04 09:45:54.554: E/AndroidRuntime(19873): java.lang.RuntimeException: An error occured while executing doInBackground()
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.lang.Thread.run(Thread.java:1019)
05-04 09:45:54.554: E/AndroidRuntime(19873): Caused by: android.database.sqlite.SQLiteMisuseException: library routine called out of sequence: , while compiling: SELECT _id, comment FROM comments
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:42)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:330)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at com.example.providertest.CommentProvider.query(CommentProvider.java:103)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.content.ContentProvider$Transport.query(ContentProvider.java:187)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.content.ContentResolver.query(ContentResolver.java:262)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123)
05-04 09:45:54.554: E/AndroidRuntime(19873):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
05-04 09:45:54.554: E/AndroidRuntime(19873):    ... 4 more
05-04 09:45:54.578: D/dalvikvm(19873): GC_CONCURRENT freed 451K, 48% free 3109K/5959K, external 876K/1388K, paused 5ms+6ms

The relevant code is in your your CommentProvider class. 相关代码在您的CommentProvider类中。 It looks like you don't open the database before trying to query it. 看起来您在尝试查询数据库之前没有打开数据库。 Hard to say without seeing the Comment Provider code. 很难说,而没有看到Comment Provider代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM