Rxjava2_Flowable_Sqlite_Android數(shù)據(jù)庫訪問實(shí)例
一、使用Rxjava訪問數(shù)據(jù)庫的優(yōu)點(diǎn):
1.隨意的線程控制,數(shù)據(jù)庫操作在一個(gè)線程,返回?cái)?shù)據(jù)處理在ui線程
2.隨時(shí)訂閱和取消訂閱,而不必再使用回調(diào)函數(shù)
3.對(duì)讀取的數(shù)據(jù)用rxjava進(jìn)行過濾,流式處理
4.使用sqlbrite可以原生返回rxjava的格式,同時(shí)是響應(yīng)式數(shù)據(jù)庫框架
(有數(shù)據(jù)添加和更新時(shí)自動(dòng)調(diào)用之前訂閱了的讀取函數(shù),達(dá)到有數(shù)據(jù)添加自動(dòng)更新ui的效果,
同時(shí)這個(gè)特性沒有禁止的方法,只能通過取消訂閱停止這個(gè)功能,對(duì)于有的框架這反而是一種累贅)
二、接下來之關(guān)注實(shí)現(xiàn)過程:
本次實(shí)現(xiàn)用rxjava2的Flowable,有被壓支持(在不需要被壓支持的情況建議使用Observable)
實(shí)現(xiàn)一個(gè)穩(wěn)健的的可靈活切換其他數(shù)據(jù)庫的結(jié)構(gòu),當(dāng)然是先定義數(shù)據(jù)庫訪問接口。然后跟具不同的數(shù)據(jù)庫實(shí)現(xiàn)接口的方法
定義接口:(對(duì)于update,delete,insert,可以選擇void類型,來簡(jiǎn)化調(diào)用代碼,但缺少了執(zhí)行結(jié)果判斷)
public interface DbSource {
//String sql = "insert into table_task (tid,startts) values(tid,startts)";
Flowable<Boolean> insertNewTask(int tid, int startts);
//String sql = "select * from table_task";
Flowable<List<TaskItem>> getAllTask();
//String sql = "select * from table_task where endts = 0";
Flowable<Optional<TaskItem>> getRunningTask();
//String sql = "update table_task set isuploadend=isuploadend where tid=tid";
Flowable<Boolean> markUploadEnd(int tid, boolean isuploadend);
//String sql = "delete from table_task where tid=tid and endts>0";
Flowable<Boolean> deleteTask(int tid);
}
三、用Android原生的Sqlite實(shí)現(xiàn)數(shù)據(jù)庫操作
public class SimpleDb implements DbSource {
private static SimpleDb sqlite;
private SqliteHelper sqliteHelper;
private SimpleDb(Context context) {
this.sqliteHelper = new SqliteHelper(context);
}
public static synchronized SimpleDb getInstance(Context context) {
if (sqlite == null )
sqlite = new SimpleDb(context);
return sqlite;
}
Flowable<Boolean> insertNewTask(int tid, int startts) {
return Flowable.create(new FlowableOnSubscribe<Boolean>() {
@Override
public void subscribe(FlowableEmitter<Boolean> e) throws Exception {
//這里數(shù)據(jù)庫操作只做示例代碼,主要關(guān)注rxjava的Flowable使用方法
ContentValues values = new ContentValues();
values.put(“tid”, 1);
values.put(“startts”,13233);
if(sqliteHelper.getWriteableDatabase().insert(TABLE_NAME, null, values) != -1)
e.onNext(true);
else
e.onNext(false);
e.onComplete();
}
}, BackpressureStrategy.BUFFER);
}
Flowable<List<TaskItem>> getAllTask() {
return Flowable.create(new FlowableOnSubscribe<List<TaskItem>>() {
@Override
public void subscribe(FlowableEmitter<List<TaskItem>> e) throws Exception {
List<TaskItem> taskList = new ArrayList<>();
StringBuilder sql = new StringBuilder(100);
sql.append("select * from ");
sql.append(SqliteHelper.TABLE_NAME_TASK);
SQLiteDatabase sqLiteDatabase = sqliteHelper.getReadableDatabase();
Cursor cursor = sqLiteDatabase.rawQuery(sql.toString(), null);
if (cursor.moveToFirst()) {
int count = cursor.getCount();
for (int a = 0; a < count; a ++) {
TaskItem item = new TaskItem();
item.setTid(cursor.getInt(1));
item.setStartts(cursor.getInt(2));
item.setEndts(cursor.getInt(3));
taskList.add(item);
cursor.move(1);
}
}
cursor.close();
sqLiteDatabase.close();
e.onNext(taskList);
e.onComplete();
}
}, BackpressureStrategy.BUFFER);
}
Flowable<Optional<TaskItem>> getRunningTask() {
return Flowable.create(new FlowableOnSubscribe<Optional<TaskItem>>() {
@Override
public void subscribe(FlowableEmitter<Optional<TaskItem>> e) throws Exception {
TaskItem item = null;
StringBuilder sql = new StringBuilder(100);
sql.append("select * from ");
sql.append(SqliteHelper.TABLE_NAME_TASK);
sql.append(" where endts=0 limit 1");
SQLiteDatabase sqLiteDatabase = sqliteHelper.getReadableDatabase();
Cursor cursor = sqLiteDatabase.rawQuery(sql.toString(), null);
if (cursor.moveToFirst()) {
int count = cursor.getCount();
if (count == 1) {
item = new TaskItem();
item.setId(cursor.getInt(0));
item.setTid(cursor.getInt(1));
item.setStartts(cursor.getInt(2));
item.setEndts(cursor.getInt(3));
}
}
cursor.close();
sqLiteDatabase.close();
e.onNext(Optional.fromNullable(item)); //import com.google.common.base.Optional;//安全檢查,待會(huì)看調(diào)用的代碼,配合rxjava很好
e.onComplete();
}
}, BackpressureStrategy.BUFFER);
}
Flowable<Boolean> markUploadEnd(int tid, boolean isuploadend) {
return Flowable.create(new FlowableOnSubscribe<Boolean>() {
@Override
public void subscribe(FlowableEmitter<Boolean> e) throws Exception {
//這里數(shù)據(jù)庫操作只做示例代碼,主要關(guān)注rxjava的Flowable使用方法
//數(shù)據(jù)庫操作代碼
e.onNext(false);//返回結(jié)果
e.onComplete();//返回結(jié)束
}
}, BackpressureStrategy.BUFFER);
}
Flowable<Boolean> deleteTask(int tid) {
return Flowable.create(new FlowableOnSubscribe<Boolean>() {
@Override
public void subscribe(FlowableEmitter<Boolean> e) throws Exception {
//這里數(shù)據(jù)庫操作只做示例代碼,主要關(guān)注rxjava的Flowable使用方法
//數(shù)據(jù)庫操作代碼
e.onNext(false);//返回結(jié)果
e.onComplete();//返回結(jié)束
}
}, BackpressureStrategy.BUFFER);
}
}
四、同一個(gè)接口使用sqlbrite的實(shí)現(xiàn)方式
public class BriteDb implements DbSource {
@NonNull
protected final BriteDatabase mDatabaseHelper;
@NonNull
private Function<Cursor, TaskItem> mTaskMapperFunction;
@NonNull
private Function<Cursor, PoiItem> mPoiMapperFunction;
@NonNull
private Function<Cursor, InterestPoiItem> mInterestPoiMapperFunction;
// Prevent direct instantiation.
private BriteDb(@NonNull Context context) {
DbHelper dbHelper = new DbHelper(context);
SqlBrite sqlBrite = new SqlBrite.Builder().build();
mDatabaseHelper = sqlBrite.wrapDatabaseHelper(dbHelper, Schedulers.io();
mTaskMapperFunction = this::getTask;
mPoiMapperFunction = this::getPoi;
mInterestPoiMapperFunction = this::getInterestPoi;
}
@Nullable
private static BriteDb INSTANCE;
public static BriteDb getInstance(@NonNull Context context) {
if (INSTANCE == null) {
INSTANCE = new BriteDb(context);
}
return INSTANCE;
}
@NonNull
private TaskItem getTask(@NonNull Cursor c) {
TaskItem item = new TaskItem();
item.setId(c.getInt(c.getColumnIndexOrThrow(PersistenceContract.TaskEntry.COLUMN_TASK_ID)));
item.setTid(c.getInt(c.getColumnIndexOrThrow(PersistenceContract.TaskEntry.COLUMN_TASK_TID)));
item.setStartts(c.getInt(c.getColumnIndexOrThrow(PersistenceContract.TaskEntry.COLUMN_TASK_STARTTS)));
item.setEndts(c.getInt(c.getColumnIndexOrThrow(PersistenceContract.TaskEntry.COLUMN_TASK_ENDTS)));
return item;
}
@Override
public void insertNewTask(int tid, int startts) {
ContentValues values = new ContentValues();
values.put(PersistenceContract.TaskEntry.COLUMN_TASK_TID, tid);
values.put(PersistenceContract.TaskEntry.COLUMN_TASK_STARTTS, startts);
mDatabaseHelper.insert(PersistenceContract.TaskEntry.TABLE_NAME_TASK, values, SQLiteDatabase.CONFLICT_REPLACE);
}
@Override
public Flowable<List<TaskItem>> getAllTask() {
String sql = String.format("SELECT * FROM %s", PersistenceContract.TaskEntry.TABLE_NAME_TASK);//TABLE_NAME_TASK表的名字字符串
return mDatabaseHelper.createQuery(PersistenceContract.TaskEntry.TABLE_NAME_TASK, sql)
.mapToList(mTaskMapperFunction)
.toFlowable(BackpressureStrategy.BUFFER);
}
@Override
public Flowable<Optional<TaskItem>> getRunningTask() {
String sql = String.format("SELECT * FROM %s WHERE %s = ? limit 1",
PersistenceContract.TaskEntry.TABLE_NAME_TASK, PersistenceContract.TaskEntry.COLUMN_TASK_ENDTS);
return mDatabaseHelper.createQuery(PersistenceContract.TaskEntry.TABLE_NAME_TASK, sql, "0")
.mapToOne(cursor -> Optional.fromNullable(mTaskMapperFunction.apply(cursor)))
.toFlowable(BackpressureStrategy.BUFFER);
}
@Override
public Flowable<Boolean> markUploadEnd(int tid, boolean isuploadend) {
return Flowable.create(new FlowableOnSubscribe<Boolean>() {
@Override
public void subscribe(FlowableEmitter<Boolean> e) throws Exception {
ContentValues values = new ContentValues();
if(isuploadend) {
values.put(PersistenceContract.TaskEntry.COLUMN_TASK_ISUPLOADEND, 1);
} else {
values.put(PersistenceContract.TaskEntry.COLUMN_TASK_ISUPLOADEND, 0);
}
String selection = PersistenceContract.TaskEntry.COLUMN_TASK_TID + " = ?";
//String[] selectionArgs = {String.valueOf(tid)};
String selectionArgs = String.valueOf(tid);
int res = mDatabaseHelper.update(PersistenceContract.TaskEntry.TABLE_NAME_TASK, values, selection, selectionArgs);
if (res > 0) {
e.onNext(true);//返回結(jié)果
} else {
e.onNext(false);//返回結(jié)果
}
e.onComplete();//返回結(jié)束
}
}, BackpressureStrategy.BUFFER);
}
@Override
public Flowable<Boolean> deleteTask(int tid) {
return Flowable.create(new FlowableOnSubscribe<Boolean>() {
@Override
public void subscribe(FlowableEmitter<Boolean> e) throws Exception {
String selection = PersistenceContract.TaskEntry.COLUMN_TASK_TID + " = ? AND "+
PersistenceContract.TaskEntry.COLUMN_TASK_ENDTS + " > 0";
String[] selectionArgs = new String[1];
selectionArgs[0] = String.valueOf(tid);
int res = mDatabaseHelper.delete(PersistenceContract.TaskEntry.TABLE_NAME_TASK, selection, selectionArgs);
if (res > 0) {
e.onNext(true);//返回結(jié)果
} else {
e.onNext(false);//返回結(jié)果
}
e.onComplete();//返回結(jié)束
}
}, BackpressureStrategy.BUFFER);
}
}
五、數(shù)據(jù)庫調(diào)用使用方法
使用了lambda簡(jiǎn)化了表達(dá)式進(jìn)一步簡(jiǎn)化代碼:
簡(jiǎn)化方法:在/app/build.gradle里面加入如下內(nèi)容:(defaultConfig的外面)
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
接口調(diào)用(獲得數(shù)據(jù)庫實(shí)例):
//全局定義的實(shí)例獲取類,以后想要換數(shù)據(jù)庫,只需在這個(gè)類里切換即可
public class Injection {
public static DbSource getDbSource(Context context) {
//choose one of them
//return BriteDb.getInstance(context);
return SimpleDb.getInstance(context);
}
}
DbSource db = Injection.getInstance(mContext);
disposable1 = db.getAllTask()
.flatMap(Flowable::fromIterable)
.filter(task -> { //自定義過濾
if (!task.getIsuploadend()) {
return true;
} else {
return false;
}
})
.subscribe(taskItems -> //這里是使用了lambda簡(jiǎn)化了表達(dá)式
doTaskProcess(taskItems)
, throwable -> {
throwable.printStackTrace();
},// onCompleted
() -> {
if (disposable1 != null && !disposable1.isDisposed()) {
disposable1.dispose();
}
});
disposable1 = db.getRunningTask()
.filter(Optional::isPresent) //判斷是否為空,為空的就跳過
.map(Optional::get) //獲取到真的參數(shù)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(taskItem -> { //onNext()
//has running task
mTid = taskItem.getTid();
}, throwable -> throwable.printStackTrace() //onError()
, () -> disposable1.dispose()); //onComplete()
disposable1 = db.markUploadEnd(tid, isuploadend)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(status -> { //onNext()
if (status) {
//dosomething
}
}, throwable -> throwable.printStackTrace() //onError()
, () -> disposable1.dispose()); //onComplete()
disposable1 = db.deleteTask(tid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(status -> { //onNext()
if (status) {
//dosomething
}
}, throwable -> throwable.printStackTrace() //onError()
, () -> disposable1.dispose()); //onComplete()
以上這篇Rxjava2_Flowable_Sqlite_Android數(shù)據(jù)庫訪問實(shí)例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android耳機(jī)插拔檢測(cè)(framework篇)原理解析
文章詳細(xì)介紹了Android系統(tǒng)中音頻設(shè)備插拔事件的處理流程,包括事件的獲取、處理和上報(bào),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-11-11
Flutter實(shí)現(xiàn)紅包動(dòng)畫效果的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用Flutter實(shí)現(xiàn)紅包的動(dòng)畫效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下2023-06-06
Android編程設(shè)置TextView顏色setTextColor用法實(shí)例
這篇文章主要介紹了Android編程設(shè)置TextView顏色setTextColor用法,結(jié)合實(shí)例形式分析了Android設(shè)置TextView顏色setTextColor、ColorStateList等方法的使用技巧與布局文件的設(shè)置方法,需要的朋友可以參考下2016-01-01
android實(shí)現(xiàn)注冊(cè)登錄程序
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)注冊(cè)登錄程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android開發(fā)設(shè)置RadioButton點(diǎn)擊效果的方法
這篇文章主要介紹了Android開發(fā)設(shè)置RadioButton點(diǎn)擊效果的方法,詳細(xì)分析了Android開發(fā)中RadioButton屬性功能及相關(guān)設(shè)置技巧,需要的朋友可以參考下2017-06-06
Android自定義View實(shí)現(xiàn)QQ消息氣泡
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)QQ消息氣泡,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
正確在Flutter中添加webview實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了正確在Flutter中添加webview實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Android 物理游戲之重力系統(tǒng)開發(fā)示例代碼
介紹Android 物理游戲之重力系統(tǒng),這里提供了詳細(xì)的資料整理,并附示例代碼和實(shí)現(xiàn)效果圖,有興趣的小伙伴可以參考下2016-08-08

