Android使用Realm数据库实现App中的收藏功能(代码详解)

作者:_彼岸雨敲窗_ 时间:2022-11-01 02:00:45 

前 言

App数据持久化功能是每个App必不可少的功能,而Android最常用的数据持久化方式主要有以下的五种方式:

  1. 使用SharedPreferences存储数据;

  2. 文件存储数据;

  3. SQLite数据库存储数据;

  4. 使用ContentProvider存储数据;

  5. 网络存储数据。

其中前四种都是缓存数据到本地,这篇主要讲的是使用第三种方式来实现App中的收藏功能,不过不用Android原生自带SQLite数据库来存储数据,而是使用第三方的Realm数据库来来存储数据。

Realm 本质上是一个嵌入式数据库,他并不是基于SQLite所构建的。它拥有自己的数据库存储引擎,可以高效且快速地完成数据库的构建操作。和SQLite不同的是,它允许你在持久层直接和数据对象工作。在它之上是一个函数式风格的查询api,众多的努力让它比传统的SQLite 操作更快 。

Realm不仅支持Android的接入,还支持IOS的接入。那么接下来就使用Realm数据库实现Android App中的收藏功能吧。

需求分析

要使用Realm数据库实现App中的收藏功能,需要实现以下几个功能和步骤:

  1. 在Android项目接入Realm数据库;

  2. 创建收藏数据库表;

  3. 实现对收藏数据库表进行增删查的操作;

  4. 数据库表增删查时界面实时渲染和更新。


接入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' 的声明,如下图

Android使用Realm数据库实现App中的收藏功能(代码详解)

在定义的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.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<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) {
  }
 })
 .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();
}

}

界面运行效果图如下:

Android使用Realm数据库实现App中的收藏功能(代码详解)

apk安装包下载体验地址:

可以扫描以下二维码进行下载安装,或者点击以下链接 http://app.fukaimei.top/MovieCollect 进行下载安装体验。

来源:https://blog.csdn.net/fukaimei/article/details/105089870

标签:android,realm,数据库,收藏
0
投稿

猜你喜欢

  • Android监听电池状态实例代码

    2022-01-31 21:28:32
  • 小米Java程序员第二轮面试10个问题 你是否会被刷掉?

    2023-11-13 09:00:29
  • Android中ListActivity用法实例分析

    2022-08-14 21:52:34
  • 详解Java中的封装、继承、多态

    2022-09-24 06:26:23
  • Kotlin 基础教程之数组容器

    2021-09-09 17:22:40
  • android照相、相册获取图片剪裁报错的解决方法

    2021-11-21 20:18:14
  • mybatis教程之resultmap_动力节点Java学院整理

    2022-09-05 22:38:37
  • java 使用JDBC构建简单的数据访问层实例详解

    2023-01-13 05:12:24
  • C# 使用PictureBox实现图片按钮控件的示例步骤

    2023-04-04 21:33:29
  • C++实现LeetCode(159.最多有两个不同字符的最长子串)

    2023-06-20 22:39:46
  • SpringBoot整合Log4j2及配置步骤

    2023-10-27 10:50:16
  • 一文掌握Spring的创建与使用

    2022-01-24 19:28:38
  • Unity3d使用FairyGUI 自定义字体的操作

    2022-05-29 16:57:27
  • Java 中的字符串常量池详解

    2023-08-15 04:43:45
  • C#生成MD5的函数代码

    2021-08-04 14:50:24
  • Java关键字之this用法详解

    2022-03-23 21:43:22
  • python、java等哪一门编程语言适合人工智能?

    2021-06-04 03:22:53
  • Android利用HorizontalScrollView仿ViewPager设计简单相册

    2022-07-29 12:28:33
  • Unity3D游戏开发数据持久化PlayerPrefs的用法详解

    2022-11-11 23:16:00
  • IDEA搭建SpringBoot离线工程的方法

    2023-04-11 05:50:42
  • asp之家 软件编程 m.aspxhome.com