本文素材来源于作者(玉念聿辉)的愚蠢操作,最近在一个项目有使用到本地数据库,一段猛如虎的操作下来后发现没法进行多线程操作,大致是报一个数据库被占用的错(具体错误忘记截图了),亲自跑度娘一趟发现使用单例模式可以解决,又一次猛如虎的操作下来发现数据插入太慢等等,因此有了这篇笔记。
我们都知道Android虽然给我们提供了一个SQLiteOpenHelper,但粗心的朋友很可能跟我一样,稍在一些细节上不注意就会引发大患。
public class DatabaseHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
//在这里创建数据库
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
//在这里可以做升级等
}
}
public class DatabaseHelper extends SQLiteOpenHelper {
final String TAG = DatabaseHelper.class.getSimpleName();
private static DatabaseHelper mInstance;
public DatabaseHelper(Context context) {
super(context, "database", null, 1);// 创建数据库名
}
//创建DatabaseHelper
public synchronized static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context);
}
return mInstance;
}
//关闭DatabaseHelper
public synchronized static void destoryInstance() {
if (mInstance != null) {
mInstance.close();
}
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table table_name(id Integer primary key autoincrement, note text,changeTime text)");// 创建表
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
/**
*不进行批量插入的插入方法(不开启事务)
*/
public synchronized void insertData(){
ContentValues values=new ContentValues();
values.put("note ", "备注");
values.put("changeTime ", new date());
getWritableDatabase().insert("table_name", null, values);
}
/**
*批量插入(开启事务)
*/
public synchronized void insertData(List cvList) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
for (ContentValues values : cvList) {
db.insert("init_table", null, values);
}
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
} catch (Exception e) {
e.printStackTrace();
} finally {
// 结束事务
db.endTransaction();
db.close();
Log.i(TAG, "插入数据库完成");
}
}
/**
* 查询数据库中table_name表数据的总条数.
* * @return
*/
public synchronized int getAllCaseNum() {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
String sql = "select count(*) from table_name";
Cursor cursor = null;
long count = 0;
try {
cursor = db.rawQuery(sql, null);
cursor.moveToFirst();
count = cursor.getLong(0);
Log.i(TAG, "init_table表总数据条数: " + count);
db.setTransactionSuccessful(); // 设置事务处理成功,不设置会自动回滚不提交
} catch (Exception e) {
e.printStackTrace();
} finally {
cursor.close();
// 结束事务
db.endTransaction();
db.close();
}
return (int) count;
}
注:
* 多线程管理开启单例模式即可(synchronized);
* 数据库的增删改查尽量开启事务来执行,执行完要记得关闭;
* Cursor使用结束记得关闭;
参见文章:https://www.cnblogs.com/zhujiabin/p/4240769.html
通过将SQLiteOpenHelper设置单例模式后,我们还是需要线程池来调用才能确保速度上的提升了,这里就简单贴一下需要注意的地方,如线程池大小、空闲时间等(也就是ThreadPoolExecutor的参数设置)。
private static final BlockingQueue POOL_QUEUE_TASK = new SynchronousQueue();
private static final ThreadFactory TASK_FACTORY = new ThreadFactory() {
private final AtomicInteger COUNT = new AtomicInteger(1);
public Thread newThread(Runnable runnable) {
int count = COUNT.getAndIncrement();
return new Thread(runnable, "Func #" + count);
}
};
/**
* 线程池
*/
public static final ExecutorService FUNC_TASK = new ThreadPoolExecutor(8,
Integer.MAX_VALUE, 3L, TimeUnit.SECONDS, POOL_QUEUE_TASK,
TASK_FACTORY);
FUNC_TASK.execute(new Runnable() {
@Override
public void run() {
//例如在这里进行调用插入数据的方法
}
});
我的第一个demo:https://blog.csdn.net/qq_35350654/article/details/94876016
Arduino学习资料:https://www.arduino.cn/thread-1066-1-1.html