Android 异步查询数据库

Android 异步查询数据库

​ 使用AsyncQueryHandler异步查询帮助类,可以实现数据库的增删改查(ContentProvidert提供的数据)。如果数据量较小的时候,使用一般的数据查询就可以实现。但是如果数据量较大,就会出现ANR(Application Not Responding)问题,这个时候也可以使用Handler,但是这样会降低效率,这个时候我们就可以使用Android已经封装好的异步查询框架AsyncQueryHandler。

​ AsyncQueryHandler内部实现:AsyncQueryHandler类封装了调用者线程与工作线程的交互过程。交互的主体是两个Handler,一个运行在调用者线程中,一个运行在工作者线程中。创建AsyncQueryHandler对象,并通过提供onXXXComplete的回调接口,实现事件的完成处理。

​ Android API中提供了四个方法:

​ startInsert:插入

​ startDelete:删除

​ startUpdate:更新

​ startQuery:查询

​ 四种方法,并有响应的onXXXComplete()方法与之相对应.于之相对应的4个onXXXComplete()方法都是空实现,因此我们完成相应调用后进行后续其他的操作可以在onXXXComplete()方法中完成.

​ 使用时直接调用startXXX方法即可。传入的通用参数如下:

参数名含义
token一个令牌,主要用来标识查询,保证唯一即可.需要跟onXXXComplete方法传入的一致。(当然你也可以不一致,同样在数据库的操作结束后会调用对应的onXXXComplete方法 )
cookie你想传给onXXXComplete方法使用的一个对象。(没有的话传递null即可)
Uri uri进行查询的通用资源标志符
projection查询的列
selection限制条件
selectionArgs查询参数
orderBy排序条件

自定义一个关于本地数据库异步操作的类:

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

import com.example.LLL.asyncsqlite.Logger;

import java.util.List;

/**
 * 数据库异步框架
 * Created by LLL on 2022/9/2.
 */
public class AsyncHandler extends Handler {

    private static final String TAG = "MasAsyncQueryHandler";

    public static final long SUCCESS = 1;
    public static final long FAIL = -1;

    private static final int EVENT_ARG_SINGLE_INSERT = 0;
    private static final int EVENT_ARG_MULTI_INSERT = 1;
    private static final int EVENT_ARG_QUERY = 2;
    private static final int EVENT_ARG_UPDATE = 3;
    private static final int EVENT_ARG_DELETE = 4;
    private static final int EVENT_INIT_DATABASE = 5;

    private static Looper sLooper = null;

    private Handler mWorkerThreadHandler;

    private IAsyncHandlerCallback mIAsyncHandlerCallback;

    protected static class SqliteArgs {
        public SQLiteDatabase db;
        public String table;
        public Handler handler;
        public IAsyncHandlerCallback callback;
    }

    protected static final class InsertSingleArgs extends SqliteArgs {
        public String nullColumnHack;
        public ContentValues values;
        public long result;
    }

    protected static final class InsertMultiArgs extends SqliteArgs {
        public String nullColumnHack;
        public List<ContentValues> valuesList;
        public long result;
    }

    protected static final class QueryArgs extends SqliteArgs {
        public boolean distinct;
        public String[] columns;
        public String whereClause;
        public String[] whereArgs;
        public String groupBy;
        public String having;
        public String orderBy;
        public String limit;
        public Cursor result;
    }

    protected static final class UpdateArgs extends SqliteArgs {
        public ContentValues values;
        public String whereClause;
        public String[] whereArgs;
        public long result;
    }

    protected static final class DeleteArgs extends SqliteArgs {
        public String whereClause;
        public String[] whereArgs;
        public long result;
    }

    protected static final class InitArgs extends SqliteArgs {
        public DataBase dbOpenHelper;
        public SQLiteDatabase result;
    }

    public AsyncHandler() {
        super();
        synchronized (AsyncHandler.class) {
            if (sLooper == null) {
                HandlerThread thread = new HandlerThread(TAG);
                thread.start();
                sLooper = thread.getLooper();
            }
        }
        mWorkerThreadHandler = new WorkerHandler(sLooper);
    }

    /**
     * 初始化数据库
     *
     * @param token        插入数据库标识
     * @param dbOpenHelper 数据库
     */
    public void initDataBase(int token, DataBase dbOpenHelper, IInitDatabaseCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_INIT_DATABASE;

        InitArgs args = new InitArgs();
        args.handler = this;
        args.dbOpenHelper = dbOpenHelper;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 单条插入数据库
     *
     * @param token          插入数据库标识
     * @param db             数据库对象
     * @param table          数据库表名
     * @param nullColumnHack 当values为空时设置的空列数据
     * @param values         插入数据库内容
     */
    public void startSingleInsert(int token, SQLiteDatabase db, String table, String nullColumnHack, ContentValues values, ISingleInsertCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_SINGLE_INSERT;

        InsertSingleArgs args = new InsertSingleArgs();
        args.handler = this;
        args.db = db;
        args.table = table;
        args.nullColumnHack = nullColumnHack;
        args.values = values;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 多条插入数据库
     *
     * @param token          插入数据库标识
     * @param db             数据库对象
     * @param table          数据库表名
     * @param nullColumnHack 当values为空时设置的空列数据
     * @param valuesList     插入数据库内容
     */
    public void startMultiInsert(int token, SQLiteDatabase db, String table, String nullColumnHack, List<ContentValues> valuesList, IMultiInsertCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_MULTI_INSERT;

        InsertMultiArgs args = new InsertMultiArgs();
        args.handler = this;
        args.db = db;
        args.table = table;
        args.nullColumnHack = nullColumnHack;
        args.valuesList = valuesList;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 查询数据库
     *
     * @param token       插入数据库标识
     * @param db          数据库对象
     * @param table       数据库表名
     * @param distinct    是否去除重复项
     * @param columns     查询的列数组
     * @param whereClause 条件
     * @param whereArgs   条件参数数组
     * @param groupBy     分组依据
     * @param having      过滤
     * @param orderBy     排序
     * @param limit       限制条数
     */
    public void startQuery(int token, SQLiteDatabase db, boolean distinct, String table, String[] columns, String whereClause, String[] whereArgs,
                           String groupBy, String having, String orderBy, String limit, IQueryCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_QUERY;

        QueryArgs args = new QueryArgs();
        args.handler = this;
        args.db = db;
        args.distinct = distinct;
        args.table = table;
        args.columns = columns;
        args.whereClause = whereClause;
        args.whereArgs = whereArgs;
        args.groupBy = groupBy;
        args.having = having;
        args.orderBy = orderBy;
        args.limit = limit;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 更新数据库
     *
     * @param token       插入数据库标识
     * @param db          数据库对象
     * @param table       数据库表名
     * @param values      更新的内容
     * @param whereClause 条件
     * @param whereArgs   条件参数数组
     */
    public void startUpdate(int token, SQLiteDatabase db, String table, ContentValues values, String whereClause, String[] whereArgs, IUpdateCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_UPDATE;

        UpdateArgs args = new UpdateArgs();
        args.handler = this;
        args.db = db;
        args.table = table;
        args.values = values;
        args.whereClause = whereClause;
        args.whereArgs = whereArgs;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 删除数据库某条
     *
     * @param token       插入数据库标识
     * @param db          数据库对象
     * @param table       数据库表名
     * @param whereClause 条件
     * @param whereArgs   条件参数数组
     */
    public void startDelete(int token, SQLiteDatabase db, String table, String whereClause, String[] whereArgs, IDeleteCallback callback) {
        Message msg = mWorkerThreadHandler.obtainMessage(token);
        msg.arg1 = EVENT_ARG_DELETE;

        DeleteArgs args = new DeleteArgs();
        args.handler = this;
        args.db = db;
        args.table = table;
        args.whereClause = whereClause;
        args.whereArgs = whereArgs;
        args.callback = callback;

        msg.obj = args;
        mWorkerThreadHandler.sendMessage(msg);
    }

    /**
     * 数据库处理
     */
    protected class WorkerHandler extends Handler {
        public WorkerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int token = msg.what;
            int event = msg.arg1;

            InsertSingleArgs insertSingleArgs;
            InsertMultiArgs insertMultiArgs;
            QueryArgs queryArgs;
            UpdateArgs updateArgs;
            DeleteArgs deleteArgs;
            InitArgs initArgs;

            Message reply;
            switch (event) {
                case EVENT_ARG_SINGLE_INSERT:
                    insertSingleArgs = (InsertSingleArgs) msg.obj;
                    insertSingleArgs.result = insertSingleArgs.db.insertOrThrow(insertSingleArgs.table,
                            insertSingleArgs.nullColumnHack, insertSingleArgs.values);
                    if ((int) insertSingleArgs.result == -1) {
                        Logger.e(TAG + " ---->> insert single args failed!");
                        insertSingleArgs.result = FAIL;
                    } else {
                        insertSingleArgs.result = SUCCESS;
                    }
                    reply = insertSingleArgs.handler.obtainMessage(token);
                    reply.obj = insertSingleArgs;
                    break;
                case EVENT_ARG_MULTI_INSERT:
                    insertMultiArgs = (InsertMultiArgs) msg.obj;
                    insertMultiArgs.db.beginTransaction();
                    for (ContentValues values : insertMultiArgs.valuesList) {
                        insertMultiArgs.result = insertMultiArgs.db.insertOrThrow(insertMultiArgs.table,
                                insertMultiArgs.nullColumnHack, values);
                        if ((int) insertMultiArgs.result == -1) {
                            Logger.e(TAG + " ---->> insert multi args failed!");
                            insertMultiArgs.result = FAIL;
                            break;
                        } else {
                            insertMultiArgs.result = SUCCESS;
                        }
                    }
                    insertMultiArgs.db.setTransactionSuccessful();
                    insertMultiArgs.db.endTransaction();
                    reply = insertMultiArgs.handler.obtainMessage(token);
                    reply.obj = insertMultiArgs;
                    break;
                case EVENT_ARG_QUERY:
                    queryArgs = (QueryArgs) msg.obj;
                    Cursor cursor;
                    try {
                        cursor = queryArgs.db.query(queryArgs.distinct, queryArgs.table,
                                queryArgs.columns, queryArgs.whereClause, queryArgs.whereArgs,
                                queryArgs.groupBy, queryArgs.having, queryArgs.orderBy, queryArgs.limit);
                        // 调用这个方法会使得主线程小小的加速,此处先遍历cursor,之后在主线程中去遍历取值时会加速,好像是这样的
                        if (cursor != null) {
                            cursor.getCount();
                        }
                    } catch (Exception e) {
                        Logger.e(TAG + " ---->> Exception thrown during handling EVENT_ARG_QUERY", e);
                        cursor = null;
                    }
                    queryArgs.result = cursor;
                    reply = queryArgs.handler.obtainMessage(token);
                    reply.obj = queryArgs;
                    break;
                case EVENT_ARG_UPDATE:
                    updateArgs = (UpdateArgs) msg.obj;
                    updateArgs.result = updateArgs.db.update(updateArgs.table, updateArgs.values, updateArgs.whereClause, updateArgs.whereArgs);
                    if ((int) updateArgs.result <= 0) {
                        Logger.e(TAG + " ---->> update args failed!");
                        updateArgs.result = FAIL;
                    } else {
                        updateArgs.result = SUCCESS;
                    }
                    reply = updateArgs.handler.obtainMessage(token);
                    reply.obj = updateArgs;
                    break;
                case EVENT_ARG_DELETE:
                    deleteArgs = (DeleteArgs) msg.obj;
                    deleteArgs.result = deleteArgs.db.delete(deleteArgs.table, deleteArgs.whereClause, deleteArgs.whereArgs);
                    if ((int) deleteArgs.result <= 0) {
                        Logger.e(TAG + " ---->> delete args failed!");
                        deleteArgs.result = FAIL;
                    } else {
                        deleteArgs.result = SUCCESS;
                    }
                    reply = deleteArgs.handler.obtainMessage(token);
                    reply.obj = deleteArgs;
                    break;
                case EVENT_INIT_DATABASE:
                    initArgs = (InitArgs) msg.obj;
                    initArgs.result = initArgs.dbOpenHelper.getWritableDatabase();
                    reply = initArgs.handler.obtainMessage(token);
                    reply.obj = initArgs;
                    break;
                default:
                    return;
            }
            reply.arg1 = msg.arg1;
            reply.sendToTarget();
        }
    }

    /**
     * 数据库处理结果回调
     */
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        int token = msg.what;
        int event = msg.arg1;

        switch (event) {
            case EVENT_ARG_SINGLE_INSERT:
                InsertSingleArgs insertSingleArgs = (InsertSingleArgs) msg.obj;
                if (insertSingleArgs.callback != null) {
                    if (insertSingleArgs.result == SUCCESS) {
                        ((ISingleInsertCallback) insertSingleArgs.callback).onSingleInsertComplete(token, insertSingleArgs.result);
                    } else {
                        insertSingleArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            case EVENT_ARG_MULTI_INSERT:
                InsertMultiArgs insertMultiArgs = (InsertMultiArgs) msg.obj;
                if (insertMultiArgs.callback != null) {
                    if (insertMultiArgs.result ==SUCCESS) {
                        ((IMultiInsertCallback) insertMultiArgs.callback).onMultiInsertComplete(token, insertMultiArgs.result);
                    } else {
                        insertMultiArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            case EVENT_ARG_QUERY:
                QueryArgs queryArgs = (QueryArgs) msg.obj;
                if (queryArgs.callback != null) {
                    if (queryArgs.result != null) {
                        ((IQueryCallback) queryArgs.callback).onQueryComplete(token, queryArgs.result);
                    } else {
                        queryArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            case EVENT_ARG_UPDATE:
                UpdateArgs updateArgs = (UpdateArgs) msg.obj;
                if (updateArgs.callback != null) {
                    if (updateArgs.result == SUCCESS) {
                        ((IUpdateCallback) updateArgs.callback).onUpdateComplete(token, updateArgs.result);
                    } else {
                        updateArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            case EVENT_ARG_DELETE:
                DeleteArgs deleteArgs = (DeleteArgs) msg.obj;
                if (deleteArgs.callback != null) {
                    if (deleteArgs.result == SUCCESS) {
                        ((IDeleteCallback) deleteArgs.callback).onDeleteComplete(token, deleteArgs.result);
                    } else {
                        deleteArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            case EVENT_INIT_DATABASE:
                InitArgs initArgs = (InitArgs) msg.obj;
                if (initArgs.callback != null) {
                    if (initArgs.result != null) {
                        ((IInitDatabaseCallback) initArgs.callback).onInitDatabaseComplete(token, initArgs.result);
                    } else {
                        initArgs.callback.onAsyncOperateFailed();
                    }
                }
                break;
            default:
                return;
        }
    }
}

​ 上面是主要的异步类,主要是先通过一个Handler去操作数据库,然后用另一个Handler去回调给调用者,注意其中的Looper不是主线程的消息队列,下面是异步操作的回调,用于通知发起数据库操作的地方这次数据库操作的结果:

/**
 * 数据库异步操作结果回调基类
 * Created by LLL on 2022/9/2.
 */
public interface IAsyncHandlerCallback {

    void onAsyncOperateFailed();

}

public interface IInitDatabaseCallback extends IAsyncHandlerCallback {

    /**
     * 初始化成功
     */
    void onInitDatabaseComplete(int token, SQLiteDatabase db);
}

public interface ISingleInsertCallback extends IAsyncHandlerCallback {
    /**
     * 单条插入成功
     */
    void onSingleInsertComplete(int token, long result);
}

public interface IMultiInsertCallback extends IAsyncHandlerCallback {

    /**
     * 多条插入成功
     */
    void onMultiInsertComplete(int token, long result);
}

public interface IQueryCallback extends IAsyncHandlerCallback{

    /**
     * 查询成功
     */
    void onQueryComplete(int token, Cursor cursor);
}

public interface IUpdateCallback extends IAsyncHandlerCallback {

    /**
     * 更新成功
     */
    void onUpdateComplete(int token, long result);
}

public interface IDeleteCallback extends IAsyncHandlerCallback {

    /**
     * 删除成功
     */
    void onDeleteComplete(int token, long result);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值