目录
文章素材数据库1、认识一下SQLiteOpenHelper2、创建单例模式SQLiteOpenHelper3、单例模式下的增删改查
线程池1、示列2、调用
总结
文章素材
本文素材来源于作者(玉念聿辉)的愚蠢操作,最近在一个项目有使用到本地数据库,一段猛如虎的操作下来后发现没法进行多线程操作,大致是报一个数据库被占用的错(具体错误忘记截图了),亲自跑度娘一趟发现使用单例模式可以解决,又一次猛如虎的操作下来发现数据插入太慢等等,因此有了这篇笔记。
数据库
我们都知道Android虽然给我们提供了一个SQLiteOpenHelper,但粗心的朋友很可能跟我一样,稍在一些细节上不注意就会引发大患。
1、认识一下SQLiteOpenHelper
public class DatabaseHelper extends SQLiteOpenHelper {
@Override
public void onCreate(SQLiteDatabase db) {
//在这里创建数据库
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
//在这里可以做升级等
}
}
2、创建单例模式SQLiteOpenHelper
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) {
}
3、单例模式下的增删改查
/**
*不进行批量插入的插入方法(不开启事务)
*/
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<ContentValues> 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的参数设置)。
1、示列
private static final BlockingQueue<Runnable> POOL_QUEUE_TASK = new SynchronousQueue<Runnable>();
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);
2、调用
FUNC_TASK.execute(new Runnable() {
@Override
public void run() {
//例如在这里进行调用插入数据的方法
}
});
总结
开发速度固然重要,但实际过程中我们往往会忽略一些简单的细节处理,希望每一次bug都是我们成长的见证,文章仅作为笔记,如有错误欢迎大家指点。
最后推荐一款学习硬件开发的IDE,对于我这种菜鸟C|C++的人来说,Arduino确实是一个不错的选择。
我的第一个demo:https://blog.csdn.net/qq_35350654/article/details/94876016 Arduino学习资料:https://www.arduino.cn/thread-1066-1-1.html