[android数据库同步]架构一种Android界面数据同步刷新机制

Posted sqlserver-mysql

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[android数据库同步]架构一种Android界面数据同步刷新机制相关的知识,希望对你有一定的参考价值。

我们来谈谈客户端界面的数据同步问题。

界面数据同步的需求

比如,下面的AB两个界面中都显示了学生Leslie的信息,当我们在A界面修改学生学号时,我们希望回到B界面时,学生的信息也能跟着改变,才能保证业务数据的正确和一致性。

这就涉及到数据的同步和刷新问题。

技术图片

主界面显示了学生和老师的信息

技术图片

另一个界面也显示了学生的信息

刷新数据时都要从数据源再次请求数据吗?

如今手机应用的数据几乎都来自网络(或者本地数据库)。假如我们在A界面上修改了学生的信息并同步到网络,若回到B界面需要刷新该学生的信息,再次调用网络请求得到学生的信息显示在B界面,这是可以的,但会大大增加服务器的负担或影响应用的响应速度,而且当用户到达一定的数量级,客户端频繁的网络请求迟早会把服务器搞垮。

如何避免频繁的网络请求同时也能实现客户端界面数据的正确性和一致性的呢?

对于上述问题,大多应用的解决方法是把网络请求得到的业务数据缓存在内存中,优先使用内存缓存数据。

这样做的理由是:

我们假定一个正常的普通用户,同一时刻只会在同一个设备上打开应用并进行业务数据操作。在这个大前提下,我们可以保证在同一时间内,不会有其他设备对服务器的同个账号数据进行更新。

于是,我们可以在第一次请求网络数据时,将请求得到的数据存在内存中,当用户对业务数据做出了操作,我们在调用API将业务数据同步到服务器后,根据用户的操作对于内存数据进行对应的更新,保证了内存数据和服务器数据的一致,在之后,直接从内存数据源取出数据供界面显示即可。

这样的方式避免了频繁、重复的API网络请求,同时使应用有较高的数据访问和响应速度。坏处是如果业务数据量庞大,应用将会占用大量的运行内存,可以通过优化来改善(我们日后再谈)。

总结一下。我们对客户端的业务数据进行刷新时,可以优先考虑从内存中读取缓存好的业务数据,特殊情况下,才考虑从网络或本地数据库请求数据。

客户端数据同步机制的设计

上面讨论好的数据存储机制为全局的数据刷新提供了一些基础。如何实现全局的数据同步机制呢?

先上架构大致的示意图。

技术图片

架构的大致示意图(模糊的话请查看原图)

看完示意图你可能就大致明白了。

简单来讲。一个Actvity里包含了多个Fragment,而每个Fragment界面如果有数据同步的需要,就委托Activity向一个叫FragmentSyncManager的类注册一个特定类型的监听回调(如学生数据、教师数据类型)。在之后的任何界面中,只要我们调用同步指令并指明要同步的数据类型,FragmentSyncManager就会找到对应数据类型的所有同步回调,并全部执行同步刷新。

原理很简单,但把它们融进架构和妥善封装是开发和程序设计的问题了。

接下来我们简单分析一下架构的实现。

架构实现

1.同步监听的定义和监听实例的管理

我们先看看同步监听类的定义:

上面的代码中,泛型T是SyncedObject的子类,SyncedObject类就是用来标明同步刷新的数据类型,我们用它来方便管理。比如学生和教师数据类型,继承这个类即可,可以不用包含什么信息,如下。

再看看刷新监听的管理类FragmentSyncManager,它包含了对同步监听的登记、注销(删除)、执行三个方法。

到这里,刷新监听的定义和管理便完成了。接下来谈谈封装方法。

2.Activity和Fragment的封装

我们再回顾一下这个示意图。

技术图片

架构的大致示意图(模糊的话请查看原图)

可以得到:每个Fragment对同步监听有三种操作,为在登记、注销、执行;同时,一个Actvity里会包含多个Fragment。

我们本可以把这三类操作放在Fragment的封装基类,但我们把同步监听的操作放到BaseActivity中,原因有几个,一是Actvity作为粒度比Fragment大的组件,应当是封装内容的最顶部,这样也可以减少创建Fragment的运行代码的内存占用;二是Activity作为系统主要的组件,需要在后台进行更复杂的同步任务(比如可以用Handler的postDelayed()定时循环同步刷新、第三方SDK监控Crash等)。对此,将同步监听的操作放在Activity更有长远的意义。如下。

显然,这三个方法是需要在Fragment中被调用的。Fragment里用getActivity()方法可以得到所在的activity,那如何让Fragment调用得到BaseActivity里的方法呢?

在上面代码中,我们让BaseActivity实现接口OnFragmentSyncedListener(这个接口包含了增、删、执行那三个方法),随后在BaseFragment里把activity转为这个接口的实例,就可以实现调用BaseActivity这三个方法了,如下。

我们看看BaseFragment的总实现。

之后,每个BaseActivity子类中的BaseFragment子类就可以使用数据同步的功能了。

如FragmentA中登记了同步监听:

技术图片

FragmentA显示了学生和老师的信息

在FragmentB中也显示了学生的信息,当我们点击按钮【UpdateStudent】更新学生信息后,FragmentA界面上的学生信息也会改变。

技术图片

FragmentB也显示了学生的信息

按钮【UpdateStudent】的响应代码如下。

上面的代码中,当执行

后,如果FragmentA此时还没有销毁的话,FragmentA中的

方法将会被执行(因为它是学生数据类型的同步监听),即实现了刷新界面。

这里还有一个更高阶的使用方法。我们可以看到,上面的onRefresh方法的形参obj就是B界面传过来的实例studentFromB,这也说明,这个架构也实现了Fragment之间值的传递,它可以用于Fragment之间的交互。

比如,我们实现了一个商品列表Fragment,也实现了一个商品搜索的Fragment,现在在商品搜索界面设定了搜索条件,点击搜索按钮后,我们希望在商品列表界面实现商品查询和加载。除了使用回调,也可以用一个夹着搜索条件的SyncedObject实例调用同步操作,在商品列表Fragment中的onRefresh方法接收到实例,并触发查询操作。

现在安卓官方出了一个叫LiveData的组件,也同样是基本内存缓存数据实现了全局刷新机制的,还加入了Fragment和Activity生命周期的控制。它的实现方式和设计原理和本文提到的内容大致相同,但更加的傻瓜化和易用,朋友们可以自行搜索查看。

以上是关于[android数据库同步]架构一种Android界面数据同步刷新机制的主要内容,如果未能解决你的问题,请参考以下文章

Android 架构组件:依赖版本的 Gradle 同步错误

android 上的 SQLite 数据库、多线程、锁和帐户同步

Android 网络时间同步-7.1

一种Android客户端架构设计分享

Android系统四层架构分享

Android clean架构的分层结构