数据库操作
- 使用事务:
- 对于多个相关的数据库更新操作,将它们包装在一个事务中。例如,当需要同时更新多个表的数据时,使用事务可以确保这些操作要么全部成功,要么全部失败,避免部分数据更新导致数据不一致问题。在Android中,通过
SQLiteDatabase
的beginTransaction()
、setTransactionSuccessful()
和endTransaction()
方法来实现事务操作。
- 示例代码:
SQLiteDatabase db = helper.getWritableDatabase();
try {
db.beginTransaction();
// 执行多个数据库更新操作
db.execSQL("UPDATE table1 SET column1 =? WHERE id =?", new String[]{"value1", "1"});
db.execSQL("UPDATE table2 SET column2 =? WHERE id =?", new String[]{"value2", "1"});
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
- 优化SQL语句:
- 对经常使用的查询语句进行优化,避免使用全表扫描。例如,为经常用于
WHERE
子句的字段添加索引。
- 示例:如果经常按照
name
字段查询用户表,可以添加索引CREATE INDEX idx_name ON user_table(name);
- 使用ContentProvider:
- 当应用中有多个组件(如Activity、Fragment等)需要访问数据库时,通过
ContentProvider
来统一对外提供数据访问接口。它提供了一种标准的机制,便于不同应用间的数据共享,同时也能在应用内部更好地管理数据库访问。
- 例如,创建一个继承自
ContentProvider
的类,在query
、insert
、update
和delete
方法中实现对数据库的操作。
缓存策略
- 内存缓存:
- 使用
LruCache
(Least Recently Used Cache)来缓存最近使用的数据。LruCache
会在缓存满时,移除最近最少使用的对象。对于频繁读取的数据库数据,可以将其缓存在内存中,减少数据库的读取次数。
- 示例代码:
private LruCache<String, Cursor> mMemoryCache;
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Cursor>(cacheSize) {
@Override
protected int sizeOf(String key, Cursor value) {
return value.getCount();
}
};
// 缓存数据
mMemoryCache.put("query_key", cursor);
// 获取缓存数据
Cursor cachedCursor = mMemoryCache.get("query_key");
- 磁盘缓存:
- 对于一些不常变化但又比较重要的数据,可以使用磁盘缓存。可以使用
DiskLruCache
来实现磁盘缓存。当内存缓存中没有找到数据时,先从磁盘缓存中查找,若还是没有则从数据库读取。
- 示例:首先初始化
DiskLruCache
,然后在需要缓存数据时,通过DiskLruCache.Editor
将数据写入磁盘,读取时通过DiskLruCache.Snapshot
读取数据。
线程管理
- 使用线程池:
- 创建一个
ThreadPoolExecutor
线程池来执行数据库操作。避免在主线程中执行数据库操作,防止主线程阻塞,影响界面响应。
- 示例代码:
ExecutorService executorService = new ThreadPoolExecutor(
3,
5,
10,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>()
);
executorService.submit(new Runnable() {
@Override
public void run() {
// 执行数据库操作
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("table_name", null, null, null, null, null, null);
// 处理查询结果
cursor.close();
db.close();
}
});
- 异步任务(AsyncTask):
- 对于一些简单的数据库操作,可以使用
AsyncTask
。它是Android提供的轻量级异步任务类,方便在后台线程执行任务,并在主线程更新UI。
- 示例:创建一个继承自
AsyncTask
的类,在doInBackground
方法中执行数据库操作,在onPostExecute
方法中更新UI。
private class DatabaseAsyncTask extends AsyncTask<Void, Void, Cursor> {
@Override
protected Cursor doInBackground(Void... params) {
SQLiteDatabase db = helper.getReadableDatabase();
return db.query("table_name", null, null, null, null, null, null);
}
@Override
protected void onPostExecute(Cursor cursor) {
// 更新UI
if (cursor != null) {
// 处理游标数据并更新UI
cursor.close();
}
}
}
new DatabaseAsyncTask().execute();
- RxJava:
- 使用RxJava进行异步操作和线程管理。通过
Observable
、Observer
模式,可以方便地将数据库操作和UI更新进行分离,并在不同的线程中执行。例如,使用subscribeOn(Schedulers.io())
指定数据库操作在I/O线程执行,observeOn(AndroidSchedulers.mainThread())
指定UI更新在主线程执行。
- 示例代码:
Observable.fromCallable(() -> {
SQLiteDatabase db = helper.getReadableDatabase();
return db.query("table_name", null, null, null, null, null, null);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Cursor>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(Cursor cursor) {
// 更新UI
if (cursor != null) {
// 处理游标数据并更新UI
cursor.close();
}
}
@Override
public void onError(Throwable e) {}
@Override
public void onComplete() {}
});