前 言

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 movieCollectDBModels = 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);

}

});

}

});

}

从数据库中删除全部影视数据的操作(删)

/**

* 清除全部收藏的数据库内容

*/

public void deleteAllCollectData() {

RealmResults 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> listener) {

RealmResults movieCollectDBModels = mRealm.where(MovieCollectDBModel.class)

.sort("createdTime", Sort.DESCENDING)

.findAllAsync();

movieCollectDBModels.addChangeListener(listener);

}

当前用户进入收藏界面的时候,需要从数据库中拉取全部的收藏数据,可以刚才添加收藏时间进行倒序排序。

数据库表增删查时界面的渲染和更新

当用户进入主页的时候,首次从网络获取数据,然后遍历一下网络获取数据是否已经有数据操作收藏数据库中,如果有的话则需要提示用户该数据已经被收藏并更改收藏图标。

public class MainActivity extends AppCompatActivity {

private MovieAdapter adapter;

private List 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 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>() {

@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 List 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.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() {

queryAllCollectData();

}

/**

* 查询本地收藏数据库中所有的数据

*/

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) {

// 根据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) {

}

})

.setPositiveButton("是", 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安装包下载体验地址:

总结

到此这篇关于Android使用Realm数据库实现App中的收藏功能(代码详解)的文章就介绍到这了,更多相关android realm数据库实现app收藏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

android收藏功能demo,Android使用Realm数据库实现App中的收藏功能(代码详解)相关推荐

  1. android开发收藏功能实现,Android使用Realm数据库如何实现App中的收藏功能

    Android使用Realm数据库如何实现App中的收藏功能 发布时间:2021-05-07 11:20:34 来源:亿速云 阅读:63 作者:小新 这篇文章主要介绍了Android使用Realm数据 ...

  2. Android实战:CoolWeather酷欧天气(加强版数据接口)代码详解(上)

    -----------------------------------该文章代码已停更,可参考浩比天气(更新于2019/6/25)----------------------------------- ...

  3. Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)

       本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 上篇文章<<Android中measure过程.WRAP_CONTENT详解以及xml布局文 ...

  4. android json mysql_Android通过json向MySQL中读写数据的方法详解【读取篇】

    本文实例讲述了Android通过json向MySQL中读取数据的方法.分享给大家供大家参考,具体如下: 首先 要定义几个解析json的方法parseJsonMulti,代码如下: private vo ...

  5. Android中联系人和通话记录详解(2)

    在文章Android中联系人和通话记录详解(1)中对通话记录进行了分析,本章将对联系人的数据库表.字段以及Insert,Query,Delelte,Update四大基本数据操作进行分析. 与联系人相关 ...

  6. android生命周期_Android开发 View的生命周期结合代码详解

    咱们以TextView控件为例: /** * Created by SunshineBoy on 2020/9/23. */ public class TestTextView extends and ...

  7. android 中的悬浮按钮,Android 中FloatingActionButton(悬浮按钮)实例详解

    android 中floatingactionbutton(悬浮按钮)实例详解 一.介绍 这个类是继承自imageview的,所以对于这个控件我们可以使用imageview的所有属性 二.使用准备, ...

  8. android mvp模式例子_Android中mvp模式使用实例详解

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一 ...

  9. php怎么自定义设置打印区域,JavaScript_jQuery实现区域打印功能代码详解,使用CSS控制打印样式,需要设 - phpStudy...

    jQuery实现区域打印功能代码详解 使用CSS控制打印样式,需要设置样式media="print",并且将页面中不需要打印的元素的样式display属性设置为none.如DEMO ...

最新文章

  1. pda找不到服务器,PDA连不上服务器常见问题分析.doc
  2. python之xlrd、xlwt学习
  3. BSP(BUSINESS SERVER PAGES)完整主机名设置及实现
  4. SourceInSight自定义命令说明与应用
  5. oracle书写高质量sql,干货!SQL性能优化,书写高质量SQL语句
  6. nodejs 30行代码 爬豆瓣电影数据
  7. c++二叉树的层序遍历_leetcode 103. 二叉树的锯齿形层序遍历
  8. 方法用于ThinkPHP3.1快速入门连贯操作
  9. 风控报表课程正式开启
  10. 中国双频前端模块市场趋势报告、技术动态创新及市场预测
  11. 【python工具】获取linux和windows系统指定接口的IP地址
  12. CTF|逆向工程软件之IDA
  13. Python:实现通过 isbn 搜索书籍算法(附完整源码)
  14. 星星之火-50:无意中发现一种能够把网络视频下载到本地计算机中的方法
  15. JAVA根据word模版使用poi导出word文档,包含图片、文字
  16. 使用国产KT148A语音芯片sop8封装,用户可以自己更换声音,低成本,高秒数
  17. 洛谷 P1618 STL全排列方法
  18. 关闭搜狗输入法-录音助手
  19. 抖音文案标题怎么写,抖音标题怎么写才能上热门:国仁楠哥
  20. xdebug(32) : warning C4229: 使用了记时错误 : 忽略数据上的修饰符

热门文章

  1. 基于STC89C52RC模块的巡线小车
  2. [转帖] 丰富多彩的开放课程资源
  3. 国庆中秋除了发月饼,企业更应该做什么?
  4. 三维目标识别、三维特征研究现状
  5. 科比26分加索尔22+9湖人首胜 爵士5虎熄火遭羞辱
  6. 美国国防高级研究计划局(DARPA)组织管理运行机制分析
  7. 用ror开发的无忧换书网,大家看看给点意见
  8. 开一家像嘀嘀那样的公司,需要办理哪些手续和多少预算?
  9. IDEA快捷键大全(详细)
  10. C Primer Plus基础教程(1)— 初步认识C语言