欢迎Follow我的GitHub, 关注我的CSDN.

本文的合集已经编著成书,高级Android开发强化实战,欢迎各位读友的建议和指导。在京东即可购买:https://item.jd.com/12385680.html

RxJava是响应式编程, 在异步处理网络数据时, 使用广泛.
我们也可以使用一些Rx的特性, 优雅地缓存网络数据.

缓存模式: 读取数据库, 显示, 请求数据, 存储到数据库, 再更新页面.

使用Dagger2+Retrofit+Rx的标准组合, 我来讲解一下如何使用.

GitHub下载地址


1. 框架

常规项目, 包含跳转缓存和非缓存页面, 为了模拟慢速环境, 延迟3秒加载数据.

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}// 跳转无缓存public void gotoNoCache(View view) {startActivity(new Intent(this, NocacheActivity.class));}// 跳转有缓存public void gotoCache(View view) {startActivity(new Intent(this, CacheActivity.class));}
}

2. 无缓存

依赖注入三个关键部分, Application/Component/Module.

public class RcApplication extends Application {private ApiComponent mApiComponent;@Override public void onCreate() {super.onCreate();mApiComponent = DaggerApiComponent.builder().apiModule(new ApiModule(this)).build();}public ApiComponent getApiComponent() {return mApiComponent;}
}
@Singleton
@Component(modules = ApiModule.class)
public interface ApiComponent {void inject(NocacheActivity activity);void inject(CacheActivity activity);
}
@Module
public class ApiModule {private Application mApplication;public ApiModule(Application application) {mApplication = application;}@Provides@Singletonpublic Application provideApplication() {return mApplication;}@Provides@Singleton GitHubClient provideGitHubClient() {return new GitHubClient();}@Provides ObservableRepoDb provideObservableRepoDb() {return new ObservableRepoDb(mApplication);}
}

模块提供应用信息, GitHub的网络请求, 数据库.
@Singleton表示单例模式, 全部注入拥有一个实例.

页面, 使用RecyclerView显示列表信息, 在加载时显示ProgressBar.

/*** 无缓存Activity* <p>* Created by wangchenlong on 16/1/18.*/
public class NocacheActivity extends Activity {@Bind(R.id.nocache_rv_list) RecyclerView mRvList;@Bind(R.id.nocache_pb_progress) ProgressBar mPbProgress;@Inject Application mApplication;@Inject GitHubClient mGitHubClient;private ListAdapter mListAdapter;@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_nocache);ButterKnife.bind(this);((RcApplication) getApplication()).getApiComponent().inject(this);LinearLayoutManager layoutManager = new LinearLayoutManager(mApplication);mRvList.setLayoutManager(layoutManager);mListAdapter = new ListAdapter();mRvList.setAdapter(mListAdapter);}@Override protected void onResume() {super.onResume();// 延迟3秒, 模拟效果mGitHubClient.getRepos("SpikeKing").delay(3, TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(this::onSuccess, this::onError);mPbProgress.setVisibility(View.VISIBLE);}private void onSuccess(ArrayList<Repo> repos) {mListAdapter.setRepos(repos);mPbProgress.setVisibility(View.INVISIBLE);}private void onError(Throwable throwable) {mPbProgress.setVisibility(View.INVISIBLE);}
}

通过观察可以发现, 长时间显示白屏会降低用户体验. 我来看看缓存模式.


3. 缓存

缓存模式: 读取数据库, 显示, 请求数据, 存储到数据库, 再更新页面.
推荐使用脚本生成数据库处理类, 使用方式参考, 自动生成DbHelper的脚本.

主页逻辑.

public class CacheActivity extends Activity {@Bind(R.id.cache_rv_list) RecyclerView mRvList; // 列表@Bind(R.id.cache_srl_swipe) SwipeRefreshLayout mSrlSwipe; // 刷新@Inject Application mApplication;@Inject ObservableRepoDb mRepoDb;@Inject GitHubClient mGitHubClient;private ListAdapter mListAdapter; // RecyclerView适配器@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_cache);ButterKnife.bind(this);// 注入类((RcApplication) getApplication()).getApiComponent().inject(this);LinearLayoutManager layoutManager = new LinearLayoutManager(mApplication);mRvList.setLayoutManager(layoutManager);mListAdapter = new ListAdapter();mRvList.setAdapter(mListAdapter);mSrlSwipe.setOnRefreshListener(this::fetchUpdates);}@Override protected void onResume() {super.onResume();mRepoDb.getObservable().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(this::setData);fetchUpdates();Toast.makeText(mApplication, "正在更新", Toast.LENGTH_SHORT).show();}// 设置数据, 更新完成会调用private void setData(ArrayList<Repo> repos) {mListAdapter.setRepos(repos);Toast.makeText(mApplication, "更新完成", Toast.LENGTH_SHORT).show();}private void fetchUpdates() {// 延迟3秒, 模拟效果mGitHubClient.getRepos("SpikeKing").delay(3, TimeUnit.SECONDS).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(mRepoDb::insertRepoList, this::fetchError, this::fetchComplete);}private void fetchError(Throwable throwable) {mSrlSwipe.setRefreshing(false);}private void fetchComplete() {mSrlSwipe.setRefreshing(false);}
}

数据库的观察者

/*** Redo的观察者* <p>* Created by wangchenlong on 16/1/18.*/
public class ObservableRepoDb {private PublishSubject<ArrayList<Repo>> mPublishSubject; // 发表主题private RepoDbHelper mDbHelper; // 数据库public ObservableRepoDb(Context context) {mDbHelper = new RepoDbHelper(context);mPublishSubject = PublishSubject.create();}// 返回观察者public Observable<ArrayList<Repo>> getObservable() {Observable<ArrayList<Repo>> firstObservable = Observable.fromCallable(this::getRepoList);return firstObservable.concatWith(mPublishSubject); // 连接发表主题}// 从数据库获得数据private ArrayList<Repo> getRepoList() {mDbHelper.openForRead();ArrayList<Repo> repos = new ArrayList<>();Cursor c = mDbHelper.getAllRepo();if (!c.moveToFirst()) {return repos; // 返回空}do {// 添加数据repos.add(new Repo(c.getString(RepoDbHelper.REPO_ID_COLUMN_POSITION),c.getString(RepoDbHelper.REPO_NAME_COLUMN_POSITION),c.getString(RepoDbHelper.REPO_DESCRIPTION_COLUMN_POSITION),new Repo.Owner(c.getString(RepoDbHelper.REPO_OWNER_COLUMN_POSITION), "", "", "")));} while (c.moveToNext());c.close();mDbHelper.close();return repos;}// 插入Repo列表public void insertRepoList(ArrayList<Repo> repos) {mDbHelper.open();mDbHelper.removeAllRepo();for (Repo repo : repos) {mDbHelper.addRepo(repo.getId(),repo.getName(),repo.getDescription(),repo.getOwner().getLogin());}mDbHelper.close();mPublishSubject.onNext(repos); // 会调用更新数据}
}

这一部分是关键, 实现网络请求同步插入数据库和更新页面.
关联PublishSubject, 在插入数据完成后, 调用绑定观察者, 更新页面.
.concatWith(mPublishSubject)mPublishSubject.onNext(repos).


Rx在处理网络请求方面, 确实非常优雅, 值得喜欢完美的人使用.

OK, that’s all! Enjoy it.

缓存网络数据--Rx和数据库相关推荐

  1. Packet Chasing:通过缓存侧信道监视网络数据包

    摘要 本文介绍了一种对网络的攻击–Packet Chasing,这种攻击不需要访问网络,无论接收数据包的进程的特权级别如何,都能发挥作用.一个间谍进程可以很容易地探测和发现网络驱动程序使用的每个缓冲区 ...

  2. 读取网络数据缓存在本地 流程图

    在C/S架构中,或者网络开发,安卓开发中.经常遇到要处理缓存的情况.根据职责分离原则,我们需要分离出缓存管理对象,必要时写个缓存接口有不同的实现,比如实现一个保存在数据库的缓存,或者物理文件的缓存. ...

  3. 智慧北京02_初步ui框架_ 主界面_viewPager事件_xUtils_slidingMenu_网络缓存_数据传递...

    智慧北京02_初步ui框架_ 主界面_viewPager事件_xUtils_slidingMenu_网络缓存_数据传递 1.使用Fragment搭建ui框架 参考分析图 1.1,Fragment生命周 ...

  4. 负载均衡服务器性能数据,用缓存服务器负载均衡 提数据库查询效率

    [IT168 资讯] 根据一些专家的调查分析,发现企业在使用数据库的时候,90%以上主要用来查询.有些企业这个比例甚至更高.也就说,用户对数据库的操作,其实更新操作占的比例很少.大部分的操走都只是查询 ...

  5. iOS开发网络——数据缓存

    一.关于同一个URL的多次请求 有时候,对同一个URL请求多次,返回的数据可能都是一样的,比如服务器上的某张图片,无论下载多少次,返回的数据都是一样的. 上面的情况会造成以下问题 (1)用户流量的浪费 ...

  6. 微服务项目实战技术点汇总:“尚硅谷的谷粒在线教育”七、redis数据库缓存页面数据、使用NUXT框架搭建前台系统环境、前台系统页面、首页轮播图(banner数据显示)、首页热门课程,名师推荐

    文章目录 一.NUXT前台环境搭建 1.如何学习NUXT 2.下载安装使用NUXT入门模板starter-template 3.机制 二.编写静态页面 1.设置布局(首尾固定,中间用nuxt引用组件) ...

  7. matlab导入桌面excel数据库,matlab导入excel数据_excel怎么导入网络上的数据?_excel导入网络数据...

    网络上的数据怎么导到excel中.有方法是直接复制然后粘贴到excel中,但是网络上直接复制过来的,可能不能直接进去下一步编辑.因为复制过来的每个词后面都有空格,是不能进行直接计算,连最基本的求和都不 ...

  8. 安卓网络数据缓存策略

    如有转载,请申明: 转载至 http://blog.csdn.net/qq_35064774/article/details/53449779 前言 对于大部分 App 来说,网络请求都是必不可少的, ...

  9. Paging3、Room使用,1、从本地Room数据库加载 2、直接网络获取数据加载 3、网络访问数据到Room数据库再加载 4、封装使用

    目录 1.从本地Room数据库加载数据 viewmodel fragment中使用 页面 数据库相关 2.直接网络获取数据加载 3.网络访问数据到Room数据库再加载数据 自定义RemoteMedia ...

最新文章

  1. python培训出来的有公司要吗-参加Python培训到底需要学什么?好程序员
  2. 解决maven cannot change version of project facet dynamic web module to 3.0
  3. Java调用Matlab程序
  4. dataframe只打印第一行_linux/unix下如何使用命令行删除文本文件的第一行?
  5. 盘点物联网的4个认知误区
  6. oracle精确匹配时间,Oracle时间精确到时、分、秒处理方法
  7. 牛客网编程题01--计算字符串最后一串单词的长度,单词以空格隔开,字符串小于5000
  8. MFC m_pMainWnd
  9. c ++结构体构造函数_C ++中的构造函数
  10. 【24点】java减治法实现二十四点,输出所有求值结果为24的组合
  11. 双十一来临,你就不想知道阿里后台都做了哪些准备吗?
  12. 减肥中,做个 体重三围 测量软件
  13. 设置用户ID位是什么意思
  14. 参加Google Developer Day 2009归来,互联网营销
  15. 分布式session会话Sticky Sessions
  16. Learning From Documents in the Wild to Improve Document Unwarping论文学习笔记
  17. ACM:nbsp;polya定理+hashnbsp;数论题nbsp;pojnbsp;3…
  18. kali、nmap扫描
  19. MarkDwon功能介绍
  20. Pdf 模板制作,itextpdf

热门文章

  1. Vue _ 教程版 02 指令
  2. 致电商小白:电商数据分析,你真的会吗?
  3. 视频管理软件技术分析报告(二)--商业VMS产品分析(Milestone)
  4. 万网虚拟主机绑定多个子域名
  5. Golang通用后台权限管理系统
  6. Docker部署web项目
  7. 小学计算机flash,小学信息技术第五册  9.初识flash软件
  8. MTK 项目工程客制化流程
  9. 【工具篇】使用concurrentHashMap实现缓存工具类
  10. php实现一个网站计数器