Android使用Realm資料庫實現App中的收藏功能(程式碼詳解)
前 言
App資料持久化功能是每個App必不可少的功能,而Android最常用的資料持久化方式主要有以下的五種方式:
- 使用SharedPreferences儲存資料;
- 檔案儲存資料;
- SQLite資料庫儲存資料;
- 使用ContentProvider儲存資料;
- 網路儲存資料。
其中前四種都是快取資料到本地,這篇主要講的是使用第三種方式來實現App中的收藏功能,不過不用Android原生自帶SQLite資料庫來儲存資料,而是使用第三方的Realm資料庫來來儲存資料。
Realm 本質上是一個嵌入式資料庫,他並不是基於SQLite所構建的。它擁有自己的資料庫儲存引擎,可以高效且快速地完成資料庫的構建操作。和SQLite不同的是,它允許你在持久層直接和資料物件工作。在它之上是一個函式式風格的查詢api,眾多的努力讓它比傳統的SQLite 操作更快 。
Realm不僅支援Android的接入,還支援IOS的接入。那麼接下來就使用Realm資料庫實現Android App中的收藏功能吧。
需求分析
要使用Realm資料庫實現App中的收藏功能,需要實現以下幾個功能和步驟:
- 在Android專案接入Realm資料庫;
- 建立收藏資料庫表;
- 實現對收藏資料庫表進行增刪查的操作;
- 資料庫表增刪查時介面實時渲染和更新。
接入Realm資料庫
然後在AS的外層build.gradle裡的buildscript.dependencies
新增Realm資料庫相關的依賴
buildscript { dependencies { ... classpath "io.realm:realm-gradle-plugin:6.0.1" } }
然後在AS的內層build.gradle裡新增Realm資料庫相關的依賴
在頂部 apply plugin: ‘com.android.application' 下新增 apply plugin: ‘realm-android' 的宣告,如下圖
在定義的Application裡初始化資料庫相關的配置(包括資料庫名稱和版本號,具體程式碼看Demo原始碼)
/** * 資料庫相關的配置 * * @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(); } }
建立收藏資料庫表
首先先建立一張收藏資料庫表,程式碼如下:
/** * 電影收藏資料庫表名 */ public class MovieCollectDBModel extends RealmObject { // 影視id,主鍵 @Required @PrimaryKey @Index private String movieId; // 影視名稱 @Required private String movieName; // 影視海報、封面 @Required private String poster; // 影視標籤 @Required private String movieLabel; // 影視型別 @Required private String videoType; // 新增到資料的時間 @Required private String createdTime; // 以下省略欄位的 set 和 get }
該類繼承於Realm的RealmObject類,其中欄位movieId作為該表的主鍵,也是資料在表裡的唯一性。
收藏資料庫表的增刪查
新增影視資料到到資料庫的操作(增)
/** * 新增收藏資料到本地資料庫 * * @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("收藏資料新增成功!"); ToastUtil.showToast(String.format("%s 已收藏",mvName)); } },new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { L.i("收藏資料新增失敗:" + error.toString()); ToastUtil.showToast(String.format("%s 收藏失敗",mvName)); } }); }
上面的程式碼是Realm資料插入資料到資料庫的操作,這是一樣非同步插入資料的方式。在業務場景的需要,可以改新增和更新資料的插入方式,比如插入資料時如果資料庫中已經存在了該資料則進行更新操作,否則進行了新增操作。
從資料庫中刪除一條影視資料的操作(刪)
/** * 通過鍵值對來刪除指定收藏資料 * * @param key * @param value */ public void deleteByKeyCollectData(String key,String value) { RealmResults<MovieCollectDBModel> movieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .equalTo(key,value) .findAllAsync(); movieCollectDBModels.addChangeListener(new RealmChangeListener<RealmResults<MovieCollectDBModel>>() { @Override public void onChange(RealmResults<MovieCollectDBModel> movieCollectDBModels1) { if (movieCollectDBModels1.isEmpty()) return; mRealm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { movieCollectDBModels1.deleteFromRealm(0); } }); } }); }
從資料庫中刪除全部影視資料的操作(刪)
/** * 清除全部收藏的資料庫內容 */ public void deleteAllCollectData() { RealmResults<MovieCollectDBModel> movieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .findAll(); mRealm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { if (movieCollectDBModels.isEmpty()) { ToastUtil.showToast("暫無收藏資料可刪除"); return; } movieCollectDBModels.deleteAllFromRealm(); ToastUtil.showToast("收藏資料已全部清空"); } }); }
從資料庫中查詢全部影視資料的操作(查)
/** * 查詢所有的收藏資料 * * @param listener */ public void queryAllCollectData(RealmChangeListener<RealmResults<MovieCollectDBModel>> listener) { RealmResults<MovieCollectDBModel> movieCollectDBModels = mRealm.where(MovieCollectDBModel.class) .sort("createdTime",Sort.DESCENDING) .findAllAsync(); movieCollectDBModels.addChangeListener(listener); }
當前使用者進入收藏介面的時候,需要從資料庫中拉取全部的收藏資料,可以剛才新增收藏時間進行倒序排序。
資料庫表增刪查時介面的渲染和更新
當用戶進入主頁的時候,首次從網路獲取資料,然後遍歷一下網路獲取資料是否已經有資料操作收藏資料庫中,如果有的話則需要提示使用者該資料已經被收藏並更改收藏圖示。
public class MainActivity extends AppCompatActivity { private MovieAdapter adapter; private List<MovieDataModel.DataBean> mList = 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) { // 跳轉至我的收藏介面 startActivity(new Intent(MainActivity.this,MovieCollectActivity.class)); } }); // 初始化本地資料庫幫助類 mRealmDBHelp = new RealmDBHelp(); } private void initRefresh() { // 開啟自動載入功能(非必須) 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; // 載入資料 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("暫無更多的資料啦"); // 將不會再次觸發載入更多事件 refreshLayout.finishLoadMoreWithNoMoreData(); refreshLayout.setEnableLoadMore(false); refreshLayout.finishLoadMore(); } },2000); } }); //觸發自動重新整理 refreshLayout.autoRefresh(); } private void initData() { // 模擬從網路獲取到json資料 app\src\main\assets\movieData.json String jsonData = BaseUtil.getAssetsJson(this,"movieData.json"); // L.i("jsonData:" + jsonData); if (TextUtils.isEmpty(jsonData)) { ToastUtil.showToast("Json資料為空"); return; } if (mList != null) mList.clear(); // 將json資料解析為Java實體物件 MovieDataModel movieDataModel = new Gson().fromJson(jsonData,MovieDataModel.class); List<MovieDataModel.DataBean> 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); } // 查詢本地收藏資料庫中是否存在收藏的資料(更改收藏圖示用的) queryAllCollectData(); try { // 設定介面卡 homeMovieList.setLayoutManager(new GridLayoutManager(this,3)); adapter = new MovieAdapter(this,mList); homeMovieList.setAdapter(adapter); } catch (Exception e) { e.printStackTrace(); } // 設定條目的點選事件 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) { // 如果已經收藏了則清除該條收藏 // 根據Id來刪除一條資料 mRealmDBHelp.deleteByKeyCollectData("movieId",mvId); mList.get(position).setCollect(false); ToastUtil.showToast(String.format("%s 已取消收藏",mvName)); } else { // 新增收藏資料到本地資料庫 mRealmDBHelp.addCollectToDB(mvId,mvName,movieImg,movieTag,videoType); mList.get(position).setCollect(true); } // 通知介面卡資料改變重新更新介面 adapter.notifyDataSetChanged(); } @Override public void onItemLongClik(View view,int position) { } }); } /** * 查詢本地收藏資料庫中是否存在收藏的資料(更改收藏圖示用的) */ private void queryAllCollectData() { mRealmDBHelp.queryAllCollectData(new RealmChangeListener<RealmResults<MovieCollectDBModel>>() { @Override public void onChange(RealmResults<MovieCollectDBModel> 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 List<MovieCollectModel> mList = 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() { // 開啟自動載入功能(非必須) 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; // 載入資料 initData(); refreshLayout.finishRefresh(); refreshLayout.resetNoMoreData();//setNoMoreData(false); } },2000); } }); //觸發自動重新整理 refreshLayout.autoRefresh(); } private void initData() { queryAllCollectData(); } /** * 查詢本地收藏資料庫中所有的資料 */ private void queryAllCollectData() { mRealmDBHelp.queryAllCollectData(new RealmChangeListener<RealmResults<MovieCollectDBModel>>() { @Override public void onChange(RealmResults<MovieCollectDBModel> 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) { // 根據Id來刪除一條資料 deleteByKeyCollectData(position); } @Override public void onItemLongClik(View view,int position) { } }); } /** * 根據Id來刪除一條資料 * * @param position */ private void deleteByKeyCollectData(int position) { IOSMsgDialog.Companion.init(getSupportFragmentManager()) .setTitle("清除影視提示") .setMessage("是否要清除該條影視收藏的資料?") .setAnimStyle(R.style.LDialogScaleAnimation) .setNegativeButton("否",new View.OnClickListener() { @Override public void onClick(View v) { } }) .setPositiveButton("是",new View.OnClickListener() { @Override public void onClick(View v) { // 根據Id來刪除一條資料 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(); } /** * 刪除本地資料庫中全部的收藏資料 */ private void deleteRealmDB() { IOSMsgDialog.Companion.init(getSupportFragmentManager()) .setTitle("清空全部收藏資料提示") .setMessage("是否要立即清空全部我的收藏的資料?如果要清除單條資料的話請點選單條資料列表。") .setAnimStyle(R.style.LDialogScaleAnimation) .setNegativeButton("否",new View.OnClickListener() { @Override public void onClick(View v) { // 清除全部收藏的資料庫內容 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(); } }
介面執行效果圖如下:
apk安裝包下載體驗地址:
可以掃描以下二維碼進行下載安裝,或者點選以下連結 http://app.fukaimei.top/MovieCollect 進行下載安裝體驗。
總結
到此這篇關於Android使用Realm資料庫實現App中的收藏功能(程式碼詳解)的文章就介紹到這了,更多相關android realm資料庫實現app收藏內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!