這篇文章主要介紹了Android使用Realm數(shù)據(jù)庫(kù)如何實(shí)現(xiàn)App中的收藏功能,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
成都創(chuàng)新互聯(lián)專注于開原企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城網(wǎng)站開發(fā)。開原網(wǎng)站建設(shè)公司,為開原等地區(qū)提供建站服務(wù)。全流程按需定制制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
App數(shù)據(jù)持久化功能是每個(gè)App必不可少的功能,而Android最常用的數(shù)據(jù)持久化方式主要有以下的五種方式:
使用SharedPreferences存儲(chǔ)數(shù)據(jù);
文件存儲(chǔ)數(shù)據(jù);
SQLite數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù);
使用ContentProvider存儲(chǔ)數(shù)據(jù);
網(wǎng)絡(luò)存儲(chǔ)數(shù)據(jù)。
其中前四種都是緩存數(shù)據(jù)到本地,這篇主要講的是使用第三種方式來(lái)實(shí)現(xiàn)App中的收藏功能,不過(guò)不用Android原生自帶SQLite數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù),而是使用第三方的Realm數(shù)據(jù)庫(kù)來(lái)來(lái)存儲(chǔ)數(shù)據(jù)。
Realm 本質(zhì)上是一個(gè)嵌入式數(shù)據(jù)庫(kù),他并不是基于SQLite所構(gòu)建的。它擁有自己的數(shù)據(jù)庫(kù)存儲(chǔ)引擎,可以高效且快速地完成數(shù)據(jù)庫(kù)的構(gòu)建操作。和SQLite不同的是,它允許你在持久層直接和數(shù)據(jù)對(duì)象工作。在它之上是一個(gè)函數(shù)式風(fēng)格的查詢api,眾多的努力讓它比傳統(tǒng)的SQLite 操作更快 。
Realm不僅支持Android的接入,還支持IOS的接入。那么接下來(lái)就使用Realm數(shù)據(jù)庫(kù)實(shí)現(xiàn)Android App中的收藏功能吧。
需求分析
要使用Realm數(shù)據(jù)庫(kù)實(shí)現(xiàn)App中的收藏功能,需要實(shí)現(xiàn)以下幾個(gè)功能和步驟:
在Android項(xiàng)目接入Realm數(shù)據(jù)庫(kù);
創(chuàng)建收藏?cái)?shù)據(jù)庫(kù)表;
實(shí)現(xiàn)對(duì)收藏?cái)?shù)據(jù)庫(kù)表進(jìn)行增刪查的操作;
數(shù)據(jù)庫(kù)表增刪查時(shí)界面實(shí)時(shí)渲染和更新。
接入Realm數(shù)據(jù)庫(kù)
然后在AS的外層build.gradle里的buildscript.dependencies
添加Realm數(shù)據(jù)庫(kù)相關(guān)的依賴
buildscript { dependencies { ... classpath "io.realm:realm-gradle-plugin:6.0.1" } }
然后在AS的內(nèi)層build.gradle里添加Realm數(shù)據(jù)庫(kù)相關(guān)的依賴
在頂部 apply plugin: ‘com.android.application' 下添加 apply plugin: ‘realm-android' 的聲明,如下圖
在定義的Application里初始化數(shù)據(jù)庫(kù)相關(guān)的配置(包括數(shù)據(jù)庫(kù)名稱和版本號(hào),具體代碼看Demo源碼)
/** * 數(shù)據(jù)庫(kù)相關(guān)的配置 * * @param context */ private void initRealm(Context context) { try { Realm.init(context); RealmConfiguration config = new RealmConfiguration.Builder() .name(RealmConstant.REALM_DB_NAME) .schemaVersion(RealmConstant.REALM_DB_VERSION) .build(); Realm.setDefaultConfiguration(config); } catch (Exception e) { e.printStackTrace(); } }
創(chuàng)建收藏?cái)?shù)據(jù)庫(kù)表
首先先創(chuàng)建一張收藏?cái)?shù)據(jù)庫(kù)表,代碼如下:
/** * 電影收藏?cái)?shù)據(jù)庫(kù)表名 */ public class MovieCollectDBModel extends RealmObject { // 影視id,主鍵 @Required @PrimaryKey @Index private String movieId; // 影視名稱 @Required private String movieName; // 影視海報(bào)、封面 @Required private String poster; // 影視標(biāo)簽 @Required private String movieLabel; // 影視類型 @Required private String videoType; // 添加到數(shù)據(jù)的時(shí)間 @Required private String createdTime; // 以下省略字段的 set 和 get }
該類繼承于Realm的RealmObject類,其中字段movieId作為該表的主鍵,也是數(shù)據(jù)在表里的唯一性。
收藏?cái)?shù)據(jù)庫(kù)表的增刪查
添加影視數(shù)據(jù)到到數(shù)據(jù)庫(kù)的操作(增)
/** * 添加收藏?cái)?shù)據(jù)到本地?cái)?shù)據(jù)庫(kù) * * @param mvId * @param mvName * @param movieImg * @param movieLabel * @param videoType */ public void addCollectToDB(String mvId, String mvName, String movieImg, String movieLabel, String videoType) { MovieCollectDBModel movieCollectDBModel = new MovieCollectDBModel(); movieCollectDBModel.setMovieId(mvId); movieCollectDBModel.setMovieName(mvName); movieCollectDBModel.setPoster(movieImg); movieCollectDBModel.setMovieLabel(movieLabel); movieCollectDBModel.setVideoType(videoType); movieCollectDBModel.setCreatedTime(BaseUtil.getNowDateTimeFormat()); mTransaction = mRealm.executeTransactionAsync(new Realm.Transaction() { @Override public void execute(Realm realm) { realm.copyToRealmOrUpdate(movieCollectDBModel); } }, new Realm.Transaction.OnSuccess() { @Override public void onSuccess() { L.i("收藏?cái)?shù)據(jù)添加成功!"); ToastUtil.showToast(String.format("%s 已收藏", mvName)); } }, new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { L.i("收藏?cái)?shù)據(jù)添加失敗:" + error.toString()); ToastUtil.showToast(String.format("%s 收藏失敗", mvName)); } }); }
上面的代碼是Realm數(shù)據(jù)插入數(shù)據(jù)到數(shù)據(jù)庫(kù)的操作,這是一樣異步插入數(shù)據(jù)的方式。在業(yè)務(wù)場(chǎng)景的需要,可以改新增和更新數(shù)據(jù)的插入方式,比如插入數(shù)據(jù)時(shí)如果數(shù)據(jù)庫(kù)中已經(jīng)存在了該數(shù)據(jù)則進(jìn)行更新操作,否則進(jìn)行了新增操作。
從數(shù)據(jù)庫(kù)中刪除一條影視數(shù)據(jù)的操作(刪)
/** * 通過(guò)鍵值對(duì)來(lái)刪除指定收藏?cái)?shù)據(jù) * * @param key * @param value */ public void deleteByKeyCollectData(String key, String value) { RealmResultsmovieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .equalTo(key, value) .findAllAsync(); movieCollectDBModels.addChangeListener(new RealmChangeListener >() { @Override public void onChange(RealmResults movieCollectDBModels1) { if (movieCollectDBModels1.isEmpty()) return; mRealm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { movieCollectDBModels1.deleteFromRealm(0); } }); } }); }
從數(shù)據(jù)庫(kù)中刪除全部影視數(shù)據(jù)的操作(刪)
/** * 清除全部收藏的數(shù)據(jù)庫(kù)內(nèi)容 */ public void deleteAllCollectData() { RealmResultsmovieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .findAll(); mRealm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { if (movieCollectDBModels.isEmpty()) { ToastUtil.showToast("暫無(wú)收藏?cái)?shù)據(jù)可刪除"); return; } movieCollectDBModels.deleteAllFromRealm(); ToastUtil.showToast("收藏?cái)?shù)據(jù)已全部清空"); } }); }
從數(shù)據(jù)庫(kù)中查詢?nèi)坑耙晹?shù)據(jù)的操作(查)
/** * 查詢所有的收藏?cái)?shù)據(jù) * * @param listener */ public void queryAllCollectData(RealmChangeListener> listener) { RealmResults movieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .sort("createdTime", Sort.DESCENDING) .findAllAsync(); movieCollectDBModels.addChangeListener(listener); }
當(dāng)前用戶進(jìn)入收藏界面的時(shí)候,需要從數(shù)據(jù)庫(kù)中拉取全部的收藏?cái)?shù)據(jù),可以剛才添加收藏時(shí)間進(jìn)行倒序排序。
數(shù)據(jù)庫(kù)表增刪查時(shí)界面的渲染和更新
當(dāng)用戶進(jìn)入主頁(yè)的時(shí)候,首次從網(wǎng)絡(luò)獲取數(shù)據(jù),然后遍歷一下網(wǎng)絡(luò)獲取數(shù)據(jù)是否已經(jīng)有數(shù)據(jù)操作收藏?cái)?shù)據(jù)庫(kù)中,如果有的話則需要提示用戶該數(shù)據(jù)已經(jīng)被收藏并更改收藏圖標(biāo)。
public class MainActivity extends AppCompatActivity { private MovieAdapter adapter; private ListmList = new ArrayList<>(); private RealmDBHelp mRealmDBHelp; private boolean refreshType; @BindView(R.id.mTitleBar) TitleBar mTitleBar; @BindView(R.id.homeMovieList) RecyclerView homeMovieList; @BindView(R.id.refreshLayout) RefreshLayout refreshLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initRefresh(); } private void initView() { ButterKnife.bind(this); mTitleBar.setOnTitleBarListener(new OnTitleBarListener() { @Override public void onLeftClick(View v) { } @Override public void onTitleClick(View v) { } @Override public void onRightClick(View v) { // 跳轉(zhuǎn)至我的收藏界面 startActivity(new Intent(MainActivity.this, MovieCollectActivity.class)); } }); // 初始化本地?cái)?shù)據(jù)庫(kù)幫助類 mRealmDBHelp = new RealmDBHelp(); } private void initRefresh() { // 開啟自動(dòng)加載功能(非必須) refreshLayout.setEnableAutoLoadMore(true); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = true; // 加載數(shù)據(jù) initData(); refreshLayout.finishRefresh(); refreshLayout.resetNoMoreData();//setNoMoreData(false); } }, 2000); } }); refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = false; ToastUtil.showToast("暫無(wú)更多的數(shù)據(jù)啦"); // 將不會(huì)再次觸發(fā)加載更多事件 refreshLayout.finishLoadMoreWithNoMoreData(); refreshLayout.setEnableLoadMore(false); refreshLayout.finishLoadMore(); } }, 2000); } }); //觸發(fā)自動(dòng)刷新 refreshLayout.autoRefresh(); } private void initData() { // 模擬從網(wǎng)絡(luò)獲取到j(luò)son數(shù)據(jù) app\src\main\assets\movieData.json String jsonData = BaseUtil.getAssetsJson(this, "movieData.json"); // L.i("jsonData:" + jsonData); if (TextUtils.isEmpty(jsonData)) { ToastUtil.showToast("Json數(shù)據(jù)為空"); return; } if (mList != null) mList.clear(); // 將json數(shù)據(jù)解析為Java實(shí)體對(duì)象 MovieDataModel movieDataModel = new Gson().fromJson(jsonData, MovieDataModel.class); List dataBeanList = movieDataModel.getData(); for (MovieDataModel.DataBean dataBean : dataBeanList) { MovieDataModel.DataBean data = new MovieDataModel.DataBean(); data.setMvid(dataBean.getMvid()); data.setName(dataBean.getName()); data.setPoster(dataBean.getPoster()); data.setUpdateStatus(dataBean.getUpdateStatus()); data.setTag(dataBean.getTag()); data.setVideo_type(dataBean.getVideo_type()); mList.add(data); } // 查詢本地收藏?cái)?shù)據(jù)庫(kù)中是否存在收藏的數(shù)據(jù)(更改收藏圖標(biāo)用的) queryAllCollectData(); try { // 設(shè)置適配器 homeMovieList.setLayoutManager(new GridLayoutManager(this, 3)); adapter = new MovieAdapter(this, mList); homeMovieList.setAdapter(adapter); } catch (Exception e) { e.printStackTrace(); } // 設(shè)置條目的點(diǎn)擊事件 adapter.setItemClikListener(new MovieAdapter.OnItemClikListener() { @Override public void onItemClik(View view, int position) { String mvId = mList.get(position).getMvid(); String mvName = mList.get(position).getName(); String movieImg = mList.get(position).getPoster(); String movieTag = mList.get(position).getTag(); String videoType = mList.get(position).getVideo_type(); boolean isCollect = mList.get(position).isCollect(); if (isCollect) { // 如果已經(jīng)收藏了則清除該條收藏 // 根據(jù)Id來(lái)刪除一條數(shù)據(jù) mRealmDBHelp.deleteByKeyCollectData("movieId", mvId); mList.get(position).setCollect(false); ToastUtil.showToast(String.format("%s 已取消收藏", mvName)); } else { // 添加收藏?cái)?shù)據(jù)到本地?cái)?shù)據(jù)庫(kù) mRealmDBHelp.addCollectToDB(mvId, mvName, movieImg, movieTag, videoType); mList.get(position).setCollect(true); } // 通知適配器數(shù)據(jù)改變重新更新界面 adapter.notifyDataSetChanged(); } @Override public void onItemLongClik(View view, int position) { } }); } /** * 查詢本地收藏?cái)?shù)據(jù)庫(kù)中是否存在收藏的數(shù)據(jù)(更改收藏圖標(biāo)用的) */ private void queryAllCollectData() { mRealmDBHelp.queryAllCollectData(new RealmChangeListener >() { @Override public void onChange(RealmResults movieCollectDBModels) { if (movieCollectDBModels.isEmpty()) { return; } for (MovieCollectDBModel movieCollectDBModel : movieCollectDBModels) { for (int i = 0; i < mList.size(); i++) { if (mList.get(i).getMvid().equals(movieCollectDBModel.getMovieId())) { mList.get(i).setCollect(true); break; } } } } }); } @Override protected void onStop() { super.onStop(); mRealmDBHelp.closeTransaction(); } @Override protected void onDestroy() { super.onDestroy(); mRealmDBHelp.close(); } }
收藏界面的代碼,包括查詢和刪除操作。
public class MovieCollectActivity extends AppCompatActivity { private RealmDBHelp mRealmDBHelp; private ListmList = new ArrayList<>(); private MovieCollectAdapter adapter; private boolean refreshType; @BindView(R.id.mTitleBar) TitleBar mTitleBar; @BindView(R.id.movieCollectList) RecyclerView movieCollectList; @BindView(R.id.empty_view) RelativeLayout empty_view; @BindView(R.id.refreshLayout) RefreshLayout refreshLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_movie_collect); initView(); initRefresh(); } private void initView() { ButterKnife.bind(this); mTitleBar.setOnTitleBarListener(new OnTitleBarListener() { @Override public void onLeftClick(View v) { finish(); } @Override public void onTitleClick(View v) { } @Override public void onRightClick(View v) { deleteRealmDB(); } }); mRealmDBHelp = new RealmDBHelp(); } private void initRefresh() { // 開啟自動(dòng)加載功能(非必須) refreshLayout.setEnableAutoLoadMore(true); refreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = true; // 加載數(shù)據(jù) initData(); refreshLayout.finishRefresh(); refreshLayout.resetNoMoreData();//setNoMoreData(false); } }, 2000); } }); refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore(@NonNull final RefreshLayout refreshLayout) { refreshLayout.getLayout().postDelayed(new Runnable() { @Override public void run() { refreshType = false; ToastUtil.showToast("暫無(wú)更多的數(shù)據(jù)啦"); // 將不會(huì)再次觸發(fā)加載更多事件 refreshLayout.finishLoadMoreWithNoMoreData(); refreshLayout.setEnableLoadMore(false); refreshLayout.finishLoadMore(); } }, 2000); } }); //觸發(fā)自動(dòng)刷新 refreshLayout.autoRefresh(); } private void initData() { queryAllCollectData(); } /** * 查詢本地收藏?cái)?shù)據(jù)庫(kù)中所有的數(shù)據(jù) */ private void queryAllCollectData() { mRealmDBHelp.queryAllCollectData(new RealmChangeListener >() { @Override public void onChange(RealmResults movieCollectDBModels) { if (movieCollectDBModels.isEmpty()) { return; } if (mList != null) mList.clear(); for (MovieCollectDBModel movieCollectDBModel : movieCollectDBModels) { MovieCollectModel data = new MovieCollectModel(); data.setMovieId(movieCollectDBModel.getMovieId()); data.setMovieName(movieCollectDBModel.getMovieName()); data.setPoster(movieCollectDBModel.getPoster()); data.setMovieTag(movieCollectDBModel.getMovieLabel()); data.setVideoType(movieCollectDBModel.getVideoType()); data.setCreatedTime(movieCollectDBModel.getCreatedTime()); mList.add(data); } runOnUiThread(new Runnable() { @Override public void run() { parsingMovieList(); } }); } }); } private void parsingMovieList() { movieCollectList.setLayoutManager(new GridLayoutManager(this, 3)); adapter = new MovieCollectAdapter(this, mList); movieCollectList.setAdapter(adapter); if (mList.isEmpty()) { empty_view.setVisibility(View.VISIBLE); movieCollectList.setVisibility(View.GONE); } else { movieCollectList.setVisibility(View.VISIBLE); empty_view.setVisibility(View.GONE); } adapter.setItemClikListener(new MovieCollectAdapter.OnItemClikListener() { @Override public void onItemClik(View view, int position) { // 根據(jù)Id來(lái)刪除一條數(shù)據(jù) deleteByKeyCollectData(position); } @Override public void onItemLongClik(View view, int position) { } }); } /** * 根據(jù)Id來(lái)刪除一條數(shù)據(jù) * * @param position */ private void deleteByKeyCollectData(int position) { IOSMsgDialog.Companion.init(getSupportFragmentManager()) .setTitle("清除影視提示") .setMessage("是否要清除該條影視收藏的數(shù)據(jù)?") .setAnimStyle(R.style.LDialogScaleAnimation) .setNegativeButton("否", new View.OnClickListener() { @Override public void onClick(View v) { } }) .setPositiveButton("是", new View.OnClickListener() { @Override public void onClick(View v) { // 根據(jù)Id來(lái)刪除一條數(shù)據(jù) mRealmDBHelp.deleteByKeyCollectData("movieId", mList.get(position).getMovieId()); mList.remove(position); adapter.notifyDataSetChanged(); } }, Color.RED) .setDismissListener(new OnDialogDismissListener() { @Override public void onDismiss(DialogInterface dialog) { } }).setCancelableOutside(true).show(); } /** * 刪除本地?cái)?shù)據(jù)庫(kù)中全部的收藏?cái)?shù)據(jù) */ private void deleteRealmDB() { IOSMsgDialog.Companion.init(getSupportFragmentManager()) .setTitle("清空全部收藏?cái)?shù)據(jù)提示") .setMessage("是否要立即清空全部我的收藏的數(shù)據(jù)?如果要清除單條數(shù)據(jù)的話請(qǐng)點(diǎn)擊單條數(shù)據(jù)列表。") .setAnimStyle(R.style.LDialogScaleAnimation) .setNegativeButton("否", new View.OnClickListener() { @Override public void onClick(View v) { } }) .setPositiveButton("是", new View.OnClickListener() { @Override public void onClick(View v) { // 清除全部收藏的數(shù)據(jù)庫(kù)內(nèi)容 mRealmDBHelp.deleteAllCollectData(); mList.clear(); empty_view.setVisibility(View.VISIBLE); movieCollectList.setVisibility(View.GONE); adapter.notifyDataSetChanged(); } }, Color.RED) .setDismissListener(new OnDialogDismissListener() { @Override public void onDismiss(DialogInterface dialog) { } }).setCancelableOutside(true).show(); } @Override protected void onDestroy() { super.onDestroy(); mRealmDBHelp.close(); } }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android使用Realm數(shù)據(jù)庫(kù)如何實(shí)現(xiàn)App中的收藏功能”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!