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.對讀取的數(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è)功能,對于有的框架這反而是一種累贅)
二、接下來之關(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)接口的方法
定義接口:(對于update,delete,insert,可以選擇void類型,來簡化調(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簡化了表達(dá)式進(jì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簡化了表達(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)文章
Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn)
這篇文章主要介紹了Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Android實(shí)現(xiàn)梯形TextView效果
TextView(文本框),用于顯示文本的一個(gè)控件,Android開發(fā)中經(jīng)常使用,本文講述如何實(shí)現(xiàn)一個(gè)梯形的TextView2021-05-05OkHttp攔截器在Android網(wǎng)絡(luò)中的使用和工作原理
當(dāng)涉及到Android應(yīng)用程序中的網(wǎng)絡(luò)請求處理時(shí),OkHttp是一個(gè)非常強(qiáng)大和流行的工具,其中一個(gè)關(guān)鍵的功能是攔截器,在本文中,我們將深入研究OkHttp攔截器,了解其工作原理以及如何使用它們來優(yōu)化您的Android應(yīng)用程序,需要的朋友可以參考下2023-09-09Android 有道詞典的簡單實(shí)現(xiàn)方法介紹
本篇文章小編為大家介紹,Android 有道詞典的簡單實(shí)現(xiàn)方法介紹。需要的朋友參考下2013-04-04Android實(shí)現(xiàn)WebView點(diǎn)擊攔截跳轉(zhuǎn)原生
這篇文章主要介紹了Android實(shí)現(xiàn)WebView點(diǎn)擊攔截跳轉(zhuǎn)原生,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Android Viewpager實(shí)現(xiàn)無限循環(huán)輪播圖
這篇文章主要為大家詳細(xì)介紹了Android Viewpager實(shí)現(xiàn)無限循環(huán)輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11Android實(shí)現(xiàn)閃屏及注冊和登錄界面之間的切換效果
這篇文章主要介紹了Android實(shí)現(xiàn)閃屏及注冊和登錄界面之間的切換效果,實(shí)現(xiàn)思路是先分別實(shí)現(xiàn)閃屏、注冊界面、登錄界面的活動(dòng),再用Intent將相關(guān)的活動(dòng)連接起來,實(shí)現(xiàn)不同活動(dòng)之間的跳轉(zhuǎn),對android 實(shí)現(xiàn)閃屏和界面切換感興趣的朋友一起看看吧2016-11-11