android五大存储模式
We know that the application of MVVM architecture pattern in Android app project will really help in building clean and structured code. The main reason is MVVM can separate component based on their respective duties.
我们知道,MVVM架构模式在Android应用程序项目中的应用将真正帮助构建干净且结构化的代码。 主要原因是MVVM可以根据各自的职责分离组件。
In short, MVVM have 3 main component called Model — View — View Model. View component will show data and manage the user interactions, View Model will handle all request and provide all data needed for View, and Model will storing data and handle the business logic.
简而言之,MVVM具有3个主要组件,称为模型—视图—视图模型。 View组件将显示数据并管理用户交互,View Model将处理所有请求并提供View所需的所有数据,而Model将存储数据并处理业务逻辑。

But the problem is, even if you have implemented this architectural pattern correctly, some code duplication may still appear, especially when you need to accessing data from local or remote database. For instance, you need to fetch data from remote database using Retrofit. More or less, you’ll need these code below to be implemented in your View Model.
但是问题是,即使您正确地实现了这种架构模式,也可能会出现一些代码重复,尤其是当您需要从本地或远程数据库访问数据时。 例如,您需要使用Retrofit从远程数据库中获取数据。 或多或少,您需要在下面的这些代码在View模型中实现。
val book = liveData { val bookDAO = Retrofit.getClient().create(BookDAO::class.java) val book = bookDAO.getBook() emit(book)}
Put in a simple scenario, this book Live Data variable will later be observed in the View. But, you may notice that the Retrofit boilerplate codes are required to setup the DAO if you need to access some resource from remote database.
放在一个简单的场景中,这本书的 Live Data变量稍后将在View中进行观察。 但是,您可能会注意到,如果需要从远程数据库访问某些资源,则需要Retrofit样板代码来设置DAO 。
This is the problem that we want to be fixed for, in order to simplify the need of accessing data and centralize the data access in our MVVM architectural pattern.
这是我们想要解决的问题,目的是简化访问数据的需求,并将数据访问集中在我们的MVVM架构模式中。
真理的单一来源 (Single Source of Truth)
In order to centralize the data access, we need something called Single Source of Truth (SSOT).
为了集中数据访问,我们需要一种称为“真相单一来源”(SSOT)的东西。
In information systems design and theory, single source of truth (SSOT) is the practice of structuring information models and associated data schema such that every data element is mastered (or edited) in only one place.
在信息系统设计和理论中,单一真相(SSOT)是构造信息模型和相关数据模式的实践,这样每个数据元素都只能在一个地方掌握(或编辑)。
It is basically a practice to centralize your data access into a single class (based on the usage of the data). For instance, you need to access the data about book, then you have to centralize all the data access which related to book into a single class so that the other class (client) can easily fetch the book data by requesting to “source of truth” class.
从根本上讲,这是将您的数据访问集中到一个类中(根据数据的使用情况)的一种做法。 例如,您需要访问有关book的数据,然后必须将与book相关的所有数据访问集中到一个类中,以便另一个类(客户端)可以通过请求“真相来源”来轻松获取book数据。 ”课。
And because all other locations of the data access just refer back to the primary “source of truth” location, updates to the data element in the primary location propagate to the entire system without the possibility of a duplicate value somewhere being forgotten.
而且,由于数据访问的所有其他位置都只是引用回主要的“真理来源”位置,因此对主要位置中的数据元素的更新会传播到整个系统,而不会在某个地方遗漏重复值。
Deployment of a SSOT is becoming increasingly important in enterprise settings where incorrectly linked duplicate or de-normalized data elements (a direct consequence of intentional or unintentional denormalization of any explicit data model) pose a risk for retrieval of outdated, and therefore incorrect, information.
SSOT的部署在企业环境中变得越来越重要,在企业环境中,错误链接的重复数据或非规范化数据元素(任何显式数据模型的有意或无意非规范化的直接后果)会导致检索过时且因此不正确的信息的风险。
A common example would be the electronic health record, where it is imperative to accurately validate patient identity against a single referential repository, which serves as the SSOT.
一个常见的示例是电子健康记录 ,其中必须根据用作SSOT的单个参照存储库准确地验证患者身份。
仓库模式 (The Repository Pattern)
To apply the SSOT practice in our app, we need to implement the repository pattern. Repository pattern is one of the design patterns that available out there. For those who don’t know about design patterns, it’s are used as a solution to recurring problems in your applications, and the repository pattern is one of the most widely used design patterns.
要在我们的应用程序中应用SSOT做法,我们需要实现存储库模式。 存储库模式是可用的设计模式之一。 对于那些不了解设计模式的人,它被用作解决应用程序中反复出现的问题的方法,并且存储库模式是使用最广泛的设计模式之一。
Repository pattern will persist your objects and the need of having to know how those objects would be actually persisted in the underlying database, i.e., without having to be bothered about how the data persistence happens underneath. The knowledge of this persistence, i.e., the persistence logic, is encapsulated inside a class called “Repository”.
存储库模式将持久化您的对象,并且需要知道如何将这些对象实际持久地存储在基础数据库中,即,不必担心数据持久性在下面如何发生。 这种持久性的知识,即持久性逻辑,被封装在称为“存储库”的类中。
Repository pattern implements separation of concerns by abstracting the data persistence logic in your applications
存储库模式通过抽象化应用程序中的数据持久性逻辑来实现关注点分离
In essence, the Repository design pattern facilitates de-coupling of the business logic and the data access layers in your application with the former not having to have any knowledge on how data persistence would actually take place.
从本质上讲,存储库设计模式可促进应用程序中业务逻辑和数据访问层之间的分离,而前者不必了解如何真正实现数据持久性。
“Repository will mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.” — Martin Fowler
“存储库将使用类似集合的界面访问域对象,在域和数据映射层之间进行中介。” — 马丁·福勒 ( Martin Fowler)
In using the Repository design pattern, you can hide the details of how the data is eventually stored or retrieved to and from the data store. This data store can be a database, an xml file, etc. You can apply this design pattern to even hide how data that is exposed by a web service or an ORM is accessed.
在使用存储库设计模式时,您可以隐藏最终如何存储数据或从数据存储中检索数据的详细信息。 该数据存储可以是数据库,xml文件等。您可以应用此设计模式,甚至隐藏如何访问Web服务或ORM公开的数据。
“Use a Repository to separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model. The business logic should be agnostic to the type of data that comprises the data source layer. For example, the data source layer can be a database, a SharePoint list, or a Web service.” — MSDN
“使用存储库将检索数据并将其映射到实体模型的逻辑与作用在模型上的业务逻辑分开。 业务逻辑应该与构成数据源层的数据类型无关。 例如,数据源层可以是数据库,SharePoint列表或Web服务。” — MSDN
A Repository is defined as a collection of domain objects that reside in the memory.
存储库定义为驻留在内存中的域对象的集合。
在Android中实施 (Implementing in Android)
If you read the Android documentation about recommended app architecture, you may notice that Google also recommend you to use repository pattern alongside with the famous MVVM architectural pattern.
如果您阅读有关推荐的应用程序架构的Android文档,您可能会注意到Google还建议您将存储库模式与著名的MVVM架构模式一起使用。

Notice that each component depends only on the component one level below it. For example, activities and fragments depend only on a view model. The repository is the only class that depends on multiple other classes; in this example, the repository depends on a persistent data model and a remote backend data source.
请注意,每个组件仅取决于其下一级的组件。 例如,活动和片段仅取决于视图模型。 存储库是唯一依赖于多个其他类的类。 在此示例中,存储库取决于持久性数据模型和远程后端数据源。
This design creates a consistent and pleasant user experience. Regardless of whether the user comes back to the app several minutes after they’ve last closed it or several days later, they instantly see a user’s information that the app persists locally. If this data is stale, the app’s repository module starts updating the data in the background.
这种设计可创建一致且令人愉快的用户体验。 无论用户是在上次关闭应用程序后几分钟还是几天后返回应用程序,他们都会立即看到该应用程序在本地存在的用户信息。 如果此数据是过时的,则应用程序的存储库模块开始在后台更新数据。
Ok, enough theory. Let’s try to implement the repository pattern in Android.
好的,足够的理论。 让我们尝试在Android中实现存储库模式。
First thing first, let’s prepare the DAO (Data Access Object) for REST API path mapping that used by Retrofit.
首先,让我们为Retrofit使用的REST API路径映射准备DAO(数据访问对象)。
interface BookDAO { @GET("/book/latest") suspend fun getLatestBook(): Book @GET("/book/all") suspend fun getAllBooks(): List<Book>}
Second, create the DAO instance using the Retrofit builder.
其次,使用Retrofit构建器创建DAO实例。
@Module@InstallIn(ApplicationComponent::class)object RemoteDatabase { @Provides @Singleton fun provideBookDAO(): BookDAO = Retrofit.getClient().create(BookDAO::class.java)}
Notice that I use the Dagger Hilt for dependency injection purpose. I hope you have basic knowledge about it, because I’m not explaining how it works and how it should be coded in this article