簡體   English   中英

Android ContentProvider SQLite:SQLiteMisuseException

[英]Android ContentProvider SQLite : SQLiteMisuseException

我有一個簡單的ContentProvider,它遵循了vogella.com的步驟進行了一些更改,因為我使用的是android-support-v4.jar我有一個簡單的App

在此處輸入圖片說明

在這里,我有三個按鈕,一個ListFragment都使用自定義ContentProvider,我在尋找問題,但是當我嘗試加快脈沖速度時,有時我會收到一個SQLiteMisuseException文檔告訴

如果應用程序創建一個SQLiteStatement對象並允許應用程序中的多個線程同時使用它,則會發生此錯誤。

但我沒有很多線程(至少我認為)。

更新 :有時應用程序停止UI工作,但沒有響應

更新2 :我正在Galaxy ACE中測試的設備的速度響應可能有問題(有錯誤),並且Galaxy SIII可以正常工作


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

<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>

數據

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

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

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;
    }

}

錯誤

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

相關代碼在您的CommentProvider類中。 看起來您在嘗試查詢數據庫之前沒有打開數據庫。 很難說,而沒有看到Comment Provider代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM