这是我参与「第四届青训营 」笔记创作活动的第19天。
本文目前功能还未实现完全,后续完成后该行说明会删除!
基于原本仿抖音项目记录新加入的元素,提醒之后的自己
MVVM
分为了common包、discovery包、douyinapi.ui包、main.ui包splash.ui与Application的Java文件。
重点在discovery包
包下根据MVVM分为Info、model、ui,以下根据目前已有的项目实现离线缓存功能。
依赖
- 新增room依赖,在最靠近根部的build.gradle的dependencies下写入
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
之前出过的错:内部与外部的sdk版本不一样,需要注意
代码
1. 在ui包下另分了activity包、adapter包、fragment包(该包因为部分页面存在左右滑动的功能存在,不重点)
上图FontIconView文件对应实现阿里icon图标实现功能,IamgeViewAttrAdapter实现榜单的拿到url得到对应图片的功能。
adapter包下是各个需要获取数据的部分的适配器。
2. 以DiscoveryVarietyActivity文件为例:
- 创建SharedPreferences类型的对象。
SharedPreferences:一个轻量级的存储类,特别适合用于保存软件配置参数。(是用xml文件存放数据,文件存在/data/data/<'package name>/shared_prefs目录下)
private SharedPreferences sharedPreferences;
private Context mContent;
- 在initVersionList()方法中异步请求中实现onFailure()方法。
在该方法中写入loadCacheDiscoveryVersion();
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//4.缓存相关
loadCacheDiscoveryVersions();
}
- 在loadCacheDiscoveryVersion方法中实现Thread的Runnable的run方法
- 注意:看起来是直接new一个接口,实际上是匿名内部类!因为接口不能实例化,new Runnable()是一个实现接口Runnable的类的对象,后面的run方法是该类里实现的方法、
- 在run方法中首先获取db实例、获取操作类、并进行检测
- mContext在该类被使用,也可以用this代替
private void loadCacheDiscoveryVersions() {
new Thread(new Runnable() {
@Override
public void run() {
//获取db实例
AppDatabase db = Room.databaseBuilder(mContext, AppDatabase.class, "xiaoyin").build();
//获取操作类
DiscoveryVersionDao discoveryVersionDao = db.discoveryVersionDao();
//检测
discoveryVersions = discoveryVersionDao.getItems();
}
}).start();
}
- 在loadVersionList方法中判断版本jason用optInt获取的error_code是否为0,若为0,进行缓存操作
List<DiscoveryVersion> cacheDiscoveryVersions = new ArrayList<>();
并且在拿出版本信息的for循环当中增加缓存的版本数据
cacheDiscoveryVersions.add(new DiscoveryVersion(startTime, endTime, mVersion));
在跳出for循环后缓存版单版本信息
cacheDiscoveryVersions(cacheDiscoveryVersions);
- cacheDiscoveryVersions(cacheDiscoveryVersions);方法如何实现呢?
//缓存榜单版本数据
private void cacheDiscoveryVersions(List<DiscoveryVersion> discoveryVersions) {
new Thread(new Runnable() {
@Override
public void run() {
//获取db实例
AppDatabase db = Room.databaseBuilder(mContext, AppDatabase.class, "xiaoyin").build();
//获取操作类
DiscoveryVersionDao discoveryVersionDao = db.discoveryVersionDao();
//检测
for (int i = 0; i < discoveryVersions.size(); i++) {
int version = discoveryVersions.get(i).version;
//判断是否未写入
if (discoveryVersionDao.getItem(version) == null) {
discoveryVersionDao.insertItem(discoveryVersions.get(i));
}
}
}
}).start();
}
- 在初始化initVersionList()中异步请求中实现onFailure方法
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//无网络-> 加载缓存
loadCacheDiscoveries();
}
- loadCacheDisvoceries();中如何实现?
@SuppressLint("NotifyDataSetChanged")
//加载缓存数据上去
private void loadCacheDiscoveries() {
//清空数据
discoveries.clear();
new Thread(new Runnable() {
@Override
public void run() {
//获取db实例
AppDatabase db = Room.databaseBuilder(mContext, AppDatabase.class, "xiaoyin").build();
//获取操作类
DiscoveryDao discoveryDao = db.discoveryDao();
//这里判断一下,如果是初始化,没有version,就记录为0
int mVersion = 0;
if (version != null) mVersion = version;
discoveries = discoveryDao.getItems(mVersion);
//getActivity.runOnUiThread(new Runnable){
runOnUiThread(new Runnable() {
@Override
public void run() {
//判断varietyAdapter是否已经创建了,创建了就再不创建了
if (varietyAdapter == null) {
//实例化CinemaMovieAdapter
varietyAdapter = new VarietyAdapter(discoveries, mContext);
//设置Adapter
binding.setVarietyAdapter(varietyAdapter);
//获取linearLayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mContext);
//设置linearLayoutManager
binding.setDiscoveryVariety(new DiscoveryVariety(linearLayoutManager, "最后一次更新"));
} else {
//通知数据变更
varietyAdapter.notifyDataSetChanged();
}
}
});
}
}).start();
}
- 在解析综艺榜单的loadVarietyList方法中判断传入的error_code是否为0,若为0,则在传入综艺所有数据后进行数据的缓存
cacheDiscoveries(discoveries);
- 实现缓存榜单数据
//缓存榜单数据
private void cacheDiscoveries(List<Discovery> discoveries) {
new Thread(new Runnable() {
@Override
public void run() {
//获取db实例
AppDatabase db = Room.databaseBuilder(mContext, AppDatabase.class, "xiaoyin").build();
//获取操作类
DiscoveryDao discoveryDao = db.discoveryDao();
//检测
for (int i = 0; i < discoveries.size(); i++) {
String id = discoveries.get(i).dataId;
//判断是否未写入
//这里判断一下,如果是初始化,没有version,就记录为0
int mVersion = 0;
if (version != null) mVersion = version;
if (discoveryDao.getItem(mVersion, id) == null) {
//没有就写入
discoveryDao.insertItem(discoveries.get(i));
}
}
}
}).start();
}
结尾
注意:
- Context可以用当前类的this代替,例如在DiscoveryVarietyActivity类则可以用下图510行替代:DiscoveryVarietyActivity.this
- 如果为当前的context的别的属性,可以忽略不写
自此,简短的离线缓存数据的实现告一段落,切记该文未完整,后续回补!