我们来谈谈客户端界面的数据同步问题。
界面数据同步的需求
比如,下面的AB两个界面中都显示了学生Leslie的信息,当我们在A界面修改学生学号时,我们希望回到B界面时,学生的信息也能跟着改变,才能保证业务数据的正确和一致性。
这就涉及到数据的同步和刷新问题。
刷新数据时都要从数据源再次请求数据吗?
如今手机应用的数据几乎都来自网络(或者本地数据库)。假如我们在A界面上修改了学生的信息并同步到网络,若回到B界面需要刷新该学生的信息,再次调用网络请求得到学生的信息显示在B界面,这是可以的,但会大大增加服务器的负担或影响应用的响应速度,而且当用户到达一定的数量级,客户端频繁的网络请求迟早会把服务器搞垮。
如何避免频繁的网络请求同时也能实现客户端界面数据的正确性和一致性的呢?
对于上述问题,大多应用的解决方法是把网络请求得到的业务数据缓存在内存中,优先使用内存缓存数据。
这样做的理由是:
我们假定一个正常的普通用户,同一时刻只会在同一个设备上打开应用并进行业务数据操作。在这个大前提下,我们可以保证在同一时间内,不会有其他设备对服务器的同个账号数据进行更新。
于是,我们可以在第一次请求网络数据时,将请求得到的数据存在内存中,当用户对业务数据做出了操作,我们在调用API将业务数据同步到服务器后,根据用户的操作对于内存数据进行对应的更新,保证了内存数据和服务器数据的一致,在之后,直接从内存数据源取出数据供界面显示即可。
这样的方式避免了频繁、重复的API网络请求,同时使应用有较高的数据访问和响应速度。坏处是如果业务数据量庞大,应用将会占用大量的运行内存,可以通过优化来改善(我们日后再谈)。
总结一下。我们对客户端的业务数据进行刷新时,可以优先考虑从内存中读取缓存好的业务数据,特殊情况下,才考虑从网络或本地数据库请求数据。
客户端数据同步机制的设计
上面讨论好的数据存储机制为全局的数据刷新提供了一些基础。如何实现全局的数据同步机制呢?
先上架构大致的示意图。
看完示意图你可能就大致明白了。
简单来讲。一个Actvity里包含了多个Fragment,而每个Fragment界面如果有数据同步的需要,就委托Activity向一个叫FragmentSyncManager的类注册一个特定类型的监听回调(如学生数据、教师数据类型)。在之后的任何界面中,只要我们调用同步指令并指明要同步的数据类型,FragmentSyncManager就会找到对应数据类型的所有同步回调,并全部执行同步刷新。
原理很简单,但把它们融进架构和妥善封装是开发和程序设计的问题了。
接下来我们简单分析一下架构的实现。
架构实现
1. 同步监听的定义和监听实例的管理
我们先看看同步监听类的定义: