├── .gitignore
├── AndroidDataStorage.iml
├── LICENSE.txt
├── README-ZH-CN.md
├── README.md
├── android-data-storage
├── .gitignore
├── android-data-storage.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── xiaofei
│ │ └── library
│ │ └── datastorage
│ │ ├── ApplicationTest.java
│ │ ├── Test01.java
│ │ └── database
│ │ ├── DbCacheConcurrency2Test.java
│ │ ├── DbCacheConcurrencyTest.java
│ │ ├── DbCacheExtremelyLongObjectTest.java
│ │ └── DbCacheTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── xiaofei
│ │ │ └── library
│ │ │ └── datastorage
│ │ │ ├── DataStorageFactory.java
│ │ │ ├── IDataStorage.java
│ │ │ ├── annotation
│ │ │ ├── AnnotationProcessor.java
│ │ │ ├── ClassId.java
│ │ │ ├── FieldMember.java
│ │ │ ├── Member.java
│ │ │ ├── MethodMember.java
│ │ │ └── ObjectId.java
│ │ │ ├── database
│ │ │ ├── DatabaseStorage.java
│ │ │ ├── DbCache.java
│ │ │ ├── DbConfig.java
│ │ │ ├── DbConst.java
│ │ │ ├── DbOpenHelper.java
│ │ │ ├── DbService.java
│ │ │ ├── DefaultCoderHook.java
│ │ │ ├── GsonObjectCoder.java
│ │ │ ├── GzipCoderHook.java
│ │ │ ├── ICoderHook.java
│ │ │ ├── IDbOperation.java
│ │ │ └── SerialObjectCoder.java
│ │ │ └── util
│ │ │ ├── CodeUtils.java
│ │ │ ├── Condition.java
│ │ │ └── GzipUtils.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── xiaofei
│ └── library
│ └── datastorage
│ └── ExampleUnitTest.java
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── xiaofei
│ │ └── library
│ │ └── datastoragetest
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── xiaofei
│ │ │ └── library
│ │ │ └── datastoragetest
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── xiaofei
│ └── library
│ └── datastoragetest
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/AndroidDataStorage.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2015-2016 Xiaofei
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
15 |
16 | Apache License
17 | Version 2.0, January 2004
18 | http://www.apache.org/licenses/
19 |
20 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
21 |
22 | 1. Definitions.
23 |
24 | "License" shall mean the terms and conditions for use, reproduction,
25 | and distribution as defined by Sections 1 through 9 of this document.
26 |
27 | "Licensor" shall mean the copyright owner or entity authorized by
28 | the copyright owner that is granting the License.
29 |
30 | "Legal Entity" shall mean the union of the acting entity and all
31 | other entities that control, are controlled by, or are under common
32 | control with that entity. For the purposes of this definition,
33 | "control" means (i) the power, direct or indirect, to cause the
34 | direction or management of such entity, whether by contract or
35 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
36 | outstanding shares, or (iii) beneficial ownership of such entity.
37 |
38 | "You" (or "Your") shall mean an individual or Legal Entity
39 | exercising permissions granted by this License.
40 |
41 | "Source" form shall mean the preferred form for making modifications,
42 | including but not limited to software source code, documentation
43 | source, and configuration files.
44 |
45 | "Object" form shall mean any form resulting from mechanical
46 | transformation or translation of a Source form, including but
47 | not limited to compiled object code, generated documentation,
48 | and conversions to other media types.
49 |
50 | "Work" shall mean the work of authorship, whether in Source or
51 | Object form, made available under the License, as indicated by a
52 | copyright notice that is included in or attached to the work
53 | (an example is provided in the Appendix below).
54 |
55 | "Derivative Works" shall mean any work, whether in Source or Object
56 | form, that is based on (or derived from) the Work and for which the
57 | editorial revisions, annotations, elaborations, or other modifications
58 | represent, as a whole, an original work of authorship. For the purposes
59 | of this License, Derivative Works shall not include works that remain
60 | separable from, or merely link (or bind by name) to the interfaces of,
61 | the Work and Derivative Works thereof.
62 |
63 | "Contribution" shall mean any work of authorship, including
64 | the original version of the Work and any modifications or additions
65 | to that Work or Derivative Works thereof, that is intentionally
66 | submitted to Licensor for inclusion in the Work by the copyright owner
67 | or by an individual or Legal Entity authorized to submit on behalf of
68 | the copyright owner. For the purposes of this definition, "submitted"
69 | means any form of electronic, verbal, or written communication sent
70 | to the Licensor or its representatives, including but not limited to
71 | communication on electronic mailing lists, source code control systems,
72 | and issue tracking systems that are managed by, or on behalf of, the
73 | Licensor for the purpose of discussing and improving the Work, but
74 | excluding communication that is conspicuously marked or otherwise
75 | designated in writing by the copyright owner as "Not a Contribution."
76 |
77 | "Contributor" shall mean Licensor and any individual or Legal Entity
78 | on behalf of whom a Contribution has been received by Licensor and
79 | subsequently incorporated within the Work.
80 |
81 | 2. Grant of Copyright License. Subject to the terms and conditions of
82 | this License, each Contributor hereby grants to You a perpetual,
83 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
84 | copyright license to reproduce, prepare Derivative Works of,
85 | publicly display, publicly perform, sublicense, and distribute the
86 | Work and such Derivative Works in Source or Object form.
87 |
88 | 3. Grant of Patent License. Subject to the terms and conditions of
89 | this License, each Contributor hereby grants to You a perpetual,
90 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
91 | (except as stated in this section) patent license to make, have made,
92 | use, offer to sell, sell, import, and otherwise transfer the Work,
93 | where such license applies only to those patent claims licensable
94 | by such Contributor that are necessarily infringed by their
95 | Contribution(s) alone or by combination of their Contribution(s)
96 | with the Work to which such Contribution(s) was submitted. If You
97 | institute patent litigation against any entity (including a
98 | cross-claim or counterclaim in a lawsuit) alleging that the Work
99 | or a Contribution incorporated within the Work constitutes direct
100 | or contributory patent infringement, then any patent licenses
101 | granted to You under this License for that Work shall terminate
102 | as of the date such litigation is filed.
103 |
104 | 4. Redistribution. You may reproduce and distribute copies of the
105 | Work or Derivative Works thereof in any medium, with or without
106 | modifications, and in Source or Object form, provided that You
107 | meet the following conditions:
108 |
109 | (a) You must give any other recipients of the Work or
110 | Derivative Works a copy of this License; and
111 |
112 | (b) You must cause any modified files to carry prominent notices
113 | stating that You changed the files; and
114 |
115 | (c) You must retain, in the Source form of any Derivative Works
116 | that You distribute, all copyright, patent, trademark, and
117 | attribution notices from the Source form of the Work,
118 | excluding those notices that do not pertain to any part of
119 | the Derivative Works; and
120 |
121 | (d) If the Work includes a "NOTICE" text file as part of its
122 | distribution, then any Derivative Works that You distribute must
123 | include a readable copy of the attribution notices contained
124 | within such NOTICE file, excluding those notices that do not
125 | pertain to any part of the Derivative Works, in at least one
126 | of the following places: within a NOTICE text file distributed
127 | as part of the Derivative Works; within the Source form or
128 | documentation, if provided along with the Derivative Works; or,
129 | within a display generated by the Derivative Works, if and
130 | wherever such third-party notices normally appear. The contents
131 | of the NOTICE file are for informational purposes only and
132 | do not modify the License. You may add Your own attribution
133 | notices within Derivative Works that You distribute, alongside
134 | or as an addendum to the NOTICE text from the Work, provided
135 | that such additional attribution notices cannot be construed
136 | as modifying the License.
137 |
138 | You may add Your own copyright statement to Your modifications and
139 | may provide additional or different license terms and conditions
140 | for use, reproduction, or distribution of Your modifications, or
141 | for any such Derivative Works as a whole, provided Your use,
142 | reproduction, and distribution of the Work otherwise complies with
143 | the conditions stated in this License.
144 |
145 | 5. Submission of Contributions. Unless You explicitly state otherwise,
146 | any Contribution intentionally submitted for inclusion in the Work
147 | by You to the Licensor shall be under the terms and conditions of
148 | this License, without any additional terms or conditions.
149 | Notwithstanding the above, nothing herein shall supersede or modify
150 | the terms of any separate license agreement you may have executed
151 | with Licensor regarding such Contributions.
152 |
153 | 6. Trademarks. This License does not grant permission to use the trade
154 | names, trademarks, service marks, or product names of the Licensor,
155 | except as required for reasonable and customary use in describing the
156 | origin of the Work and reproducing the content of the NOTICE file.
157 |
158 | 7. Disclaimer of Warranty. Unless required by applicable law or
159 | agreed to in writing, Licensor provides the Work (and each
160 | Contributor provides its Contributions) on an "AS IS" BASIS,
161 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
162 | implied, including, without limitation, any warranties or conditions
163 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
164 | PARTICULAR PURPOSE. You are solely responsible for determining the
165 | appropriateness of using or redistributing the Work and assume any
166 | risks associated with Your exercise of permissions under this License.
167 |
168 | 8. Limitation of Liability. In no event and under no legal theory,
169 | whether in tort (including negligence), contract, or otherwise,
170 | unless required by applicable law (such as deliberate and grossly
171 | negligent acts) or agreed to in writing, shall any Contributor be
172 | liable to You for damages, including any direct, indirect, special,
173 | incidental, or consequential damages of any character arising as a
174 | result of this License or out of the use or inability to use the
175 | Work (including but not limited to damages for loss of goodwill,
176 | work stoppage, computer failure or malfunction, or any and all
177 | other commercial damages or losses), even if such Contributor
178 | has been advised of the possibility of such damages.
179 |
180 | 9. Accepting Warranty or Additional Liability. While redistributing
181 | the Work or Derivative Works thereof, You may choose to offer,
182 | and charge a fee for, acceptance of support, warranty, indemnity,
183 | or other liability obligations and/or rights consistent with this
184 | License. However, in accepting such obligations, You may act only
185 | on Your own behalf and on Your sole responsibility, not on behalf
186 | of any other Contributor, and only if You agree to indemnify,
187 | defend, and hold each Contributor harmless for any liability
188 | incurred by, or claims asserted against, such Contributor by reason
189 | of your accepting any such warranty or additional liability.
190 |
191 | END OF TERMS AND CONDITIONS
192 |
--------------------------------------------------------------------------------
/README-ZH-CN.md:
--------------------------------------------------------------------------------
1 | # AndroidDataStorage
2 |
3 | 一个简洁易用并且具有高性能的Android存储库
4 |
5 | ##特色
6 |
7 | 1、实现安卓设备上的对象持久化,能存储和读取任何对象。
8 |
9 | 2、读写速度比SharedPreference等基于文件的存储方案高。
10 |
11 | 3、大量对象读写操作的场景下,使用此框架能极大提升性能,比通常的数据库方案高效。
12 |
13 | 4、上层使用缓存,读写数据快速高效。底层使用数据库,在进程被终止并重新启动后能快速恢复对象。
14 |
15 | 5、接口简单易用,用户无需了解安卓存储机制。
16 |
17 | 6、经过严格测试,有良好的容错能力和稳定性。
18 |
19 | ##Gradle
20 |
21 | ```
22 | dependencies {
23 | compile 'xiaofei.library:android-data-storage:1.3.0'
24 | }
25 | ```
26 |
27 | ##Maven
28 |
29 | ```
30 |
31 | xiaofei.library
32 | android-data-storage
33 | 1.3.0
34 | pom
35 |
36 | ```
37 |
38 | ##用法
39 |
40 | ###1. 获取接口
41 |
42 | 获取IDataStorage接口,目前只支持数据库类型。
43 | ```
44 | IDataStorage dataStorage = DataStorageFactory.getInstance(
45 | getApplicationContext(),
46 | DataStorageFactory.TYPE_DATABASE);
47 | ```
48 | ###2、存储原理
49 |
50 | 存储数据的时候,索引是类id和对象id。如果这两个id相同,则老数据被覆盖。读取数据的时候也需要提供这两个id。
51 |
52 | ###3、类id
53 |
54 | 给需要存储的类加上ClassId注解,里面写上类id。需要保证不同的类有不同的id。
55 |
56 | 如果不同版本的代码在混淆后,能保证该类的类名不变,那就不需要加注解。框架将类的包名和类名作为类id。
57 |
58 | ###4、对象id
59 |
60 | 如果类的某个字段就是对象id,那在那个字段之前加上ObjectId注解。该字段必须是String。框架将这个字段作为对象id。
61 |
62 | 如果没有这个字段,那读写数据的时候需要提供对象id作为函数的参数。
63 |
64 | 以下给出一个例子:
65 |
66 | ```
67 | @ClassId("Order")
68 | public class Order {
69 | @ObjectId
70 | private String mId;
71 |
72 | private int mState;
73 |
74 | public int getState() {
75 | return mState;
76 | }
77 | ...
78 | ...
79 | }
80 | ```
81 |
82 | ###5、APIs
83 |
84 | 下文介绍存储和读取数据的API。
85 |
86 | 所有API操作都发生在内存中,而相应的数据库操作放在了后台线程中,所以这些API都可以在主线程调用,不会阻塞主线程。
87 |
88 | ####1、存储数据
89 |
90 | 存储对象order:
91 |
92 | ```
93 | dataStorage.saveOrUpdate(order);
94 | ```
95 |
96 | 存储一个order列表:
97 |
98 | ```
99 | List list = new ArrayList();
100 | ...
101 | dataStorage.saveOrUpdate(list);
102 | ```
103 |
104 | 如果Order内部没有对象id的字段:
105 |
106 | ```
107 | dataStorage.saveOrUpdate(order, "1001");
108 |
109 | List list = new ArrayList();
110 | List ids = new ArrayList();
111 | ...
112 | //list和ids一一对应
113 | dataStorage.saveOrUpdate(list, ids);
114 | ```
115 |
116 | ####2、读取数据
117 |
118 | 读取一个数据
119 |
120 | ```
121 | Order order = dataStorage.load(Order.class, "1001");
122 | ```
123 |
124 | 读取所有Order
125 |
126 | ```
127 | List list = dataStorage.loadAll(Order.class);
128 | ```
129 |
130 | 读取mState为10的所有Order
131 |
132 | ```
133 | List list = dataStorage.load(Order.class, new Condition() {
134 | @Override
135 | public boolean satisfy(Order o) {
136 | return o.getState() == 10;
137 | }
138 | });
139 | ```
140 |
141 | 读取一批id的Order
142 |
143 | ```
144 | List ids = new ArrayList();
145 | ...
146 | List list = dataStorage.load(Order.class, ids);
147 | ```
148 |
149 | 以上函数都有一个参数Comparator供选择,提供Comparator后,获取的List是经过排序的。
150 |
151 | ```
152 | List list = dataStorage.loadAll(Order.class, comparator);
153 | ```
154 |
155 | 我还做了一个工具类,可以方便地自动生成Comparator。详见[这里](https://github.com/Xiaofei-it/ComparatorGenerator)。
156 |
157 | ####3、删除数据
158 |
159 | 删除一个数据
160 |
161 | ```
162 | dataStorage.delete(order);
163 | ```
164 |
165 | 如果Order类里没有提供对象id,那么
166 |
167 | ```
168 | dataStorage.delete(Order.class, "1001");
169 | ```
170 |
171 | 删除所有Order
172 |
173 | ```
174 | dataStorage.deleteAll(Order.class);
175 | ```
176 |
177 | 删除一批Order
178 |
179 | ```
180 | List list = new ArrayList();
181 | dataStorage.delete(list);
182 | ```
183 |
184 | 如果Order类里没有提供对象id,那么
185 |
186 | ```
187 | List ids = new ArrayList();
188 | ...
189 | dataStorage.delete(Order.class, ids);
190 | ```
191 |
192 | 删除mState为10的Order
193 |
194 |
195 | ```
196 | dataStorage.delete(Order.class, new Condition() {
197 | @Override
198 | public boolean satisfy(Order o) {
199 | return o.getState() == 10;
200 | }
201 | });
202 | ```
203 |
204 | ####4、其他API
205 |
206 | 还有许多API,具体请看[xiaofei.library.datastorage.IDataStorage](https://github.com/Xiaofei-it/AndroidDataStorage/blob/master/android-data-storage/src/main/java/xiaofei/library/datastorage/IDataStorage.java)。
207 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidDataStorage
2 | An easy-to-use and high-performance library for storing data in the Android system.
3 |
4 | [Chinese Readme 中文文档](https://github.com/Xiaofei-it/AndroidDataStorage/blob/master/README-ZH-CN.md)
5 |
6 | ##Features
7 |
8 | 1. A framework for object persistence in Android, which can store any kind of objects.
9 |
10 | 2. Using cache to improve the performance of storing and accessing data.
11 |
12 | 3. Easy to use, even if you have no knowledge of the mechanics of Android storage.
13 |
14 | 4. Good Ability of fault tolerance and high stability.
15 |
16 | ##Gradle
17 |
18 | ```
19 | dependencies {
20 | compile 'xiaofei.library:android-data-storage:1.3.0'
21 | }
22 | ```
23 |
24 | ##Maven
25 |
26 | ```
27 |
28 | xiaofei.library
29 | android-data-storage
30 | 1.3.0
31 | pom
32 |
33 | ```
34 |
35 | ##Usage
36 |
37 | ###1. Obtain the implementation of data storage
38 |
39 | Obtain the implementation of data storage through DataStorageFactory. Now it only supports the database version of data storage and more versions will be supported in the future.
40 | ```
41 | IDataStorage dataStorage = DataStorageFactory.getInstance(
42 | getApplicationContext(),
43 | DataStorageFactory.TYPE_DATABASE);
44 | ```
45 | ###2. Principle
46 |
47 | The framework stores an object according to its class's id and its own id. The former one is called the "class id" and the latter one is called the "object id".
48 |
49 | If the framework stores two objects which have the same class id and the same object id, the one stored earlier is replaced by the one stored later.
50 |
51 | The following will tell you how to give an object a class id and an object id.
52 |
53 | ###3. Class id
54 |
55 | Add a @ClassId annotation on the class you want to store. Give the annotation a value, which indicates the class id.
56 |
57 | Distinct classes should have distinct class ids.
58 |
59 | If you guarantee that the class name remains the same in different versions of apps even after ProGuard is used, then the @ClassId annotation is not necessary. In this case, if you do not add a @ClassId annotation, the class name will be the class id.
60 |
61 | ###4. Object id
62 |
63 | Often the object contains an object id as a field in itself. If there is such a field, then add an @ObjectId annotation on the field. Note that this field must be of the String type.
64 |
65 | If there is no such a field, then you should provide an object id when storing and loading the object.
66 |
67 | The following is an example illustrating how to add @ClassId and @ObjectId:
68 |
69 | ```
70 | @ClassId("Order")
71 | public class Order {
72 | @ObjectId
73 | private String mId;
74 |
75 | private int mState;
76 |
77 | public int getState() {
78 | return mState;
79 | }
80 | ...
81 | ...
82 | }
83 | ```
84 |
85 | ###5. APIs
86 |
87 | The following introduces APIs for storing and loading data.
88 |
89 | All of the APIs perform operations in the memory cache and put the database operations in the background, so feel free to call the APIs in the main thread.
90 |
91 | ####1. Storing
92 |
93 | Store an order:
94 |
95 | ```
96 | dataStorage.saveOrUpdate(order);
97 | ```
98 |
99 | Store a list of orders:
100 |
101 | ```
102 | List list = new ArrayList();
103 | ...
104 | dataStorage.saveOrUpdate(list);
105 | ```
106 |
107 | If there is no id in the Order class, then you should provide an object id:
108 |
109 | ```
110 | dataStorage.saveOrUpdate(order, "1001");
111 |
112 | List list = new ArrayList();
113 | List ids = new ArrayList();
114 | ...
115 | // Each order in the list has a corresponding id in ids.
116 | dataStorage.saveOrUpdate(list, ids);
117 | ```
118 |
119 | ####2. Loading
120 |
121 | Load an order:
122 |
123 | ```
124 | Order order = dataStorage.load(Order.class, "1001");
125 | ```
126 |
127 | Load all orders:
128 |
129 | ```
130 | List list = dataStorage.loadAll(Order.class);
131 | ```
132 |
133 | Load the orders whose state is 10:
134 |
135 | ```
136 | List list = dataStorage.load(Order.class, new Condition() {
137 | @Override
138 | public boolean satisfy(Order o) {
139 | return o.getState() == 10;
140 | }
141 | });
142 | ```
143 |
144 | Load a list of orders:
145 |
146 | ```
147 | List ids = new ArrayList();
148 | ...
149 | List list = dataStorage.load(Order.class, ids);
150 | ```
151 |
152 | Each loading method has an alternative into which you can pass a comparator as a parameter. The return value of such a method will be sorted using the comparator.
153 |
154 | ```
155 | List list = dataStorage.loadAll(Order.class, comparator);
156 | ```
157 |
158 | I have write a helper class to provide an easy way to generate a comparator. See [Here](https://github.com/Xiaofei-it/ComparatorGenerator).
159 |
160 | ####3. Deleting
161 |
162 | Delete an order:
163 |
164 | ```
165 | dataStorage.delete(order);
166 | ```
167 |
168 | If there is no id in the Order class, then you should provide an object id:
169 |
170 | ```
171 | dataStorage.delete(Order.class, "1001");
172 | ```
173 |
174 | Delete all orders:
175 |
176 | ```
177 | dataStorage.deleteAll(Order.class);
178 | ```
179 |
180 | Delete a list of orders:
181 |
182 | ```
183 | List list = new ArrayList();
184 | dataStorage.delete(list);
185 | ```
186 |
187 | If there is no id in the Order class, then you should provide object ids:
188 |
189 | ```
190 | List ids = new ArrayList();
191 | ...
192 | dataStorage.delete(Order.class, ids);
193 | ```
194 |
195 | Delete the orders whose state is 10:
196 |
197 |
198 | ```
199 | dataStorage.delete(Order.class, new Condition() {
200 | @Override
201 | public boolean satisfy(Order o) {
202 | return o.getState() == 10;
203 | }
204 | });
205 | ```
206 |
207 | ####4. Other APIs
208 |
209 | There are a lot of APIs. Please See [xiaofei.library.datastorage.IDataStorage](https://github.com/Xiaofei-it/AndroidDataStorage/blob/master/android-data-storage/src/main/java/xiaofei/library/datastorage/IDataStorage.java).
210 |
--------------------------------------------------------------------------------
/android-data-storage/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android-data-storage/android-data-storage.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/android-data-storage/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 |
5 | ext {
6 | bintrayRepo = 'maven'
7 | bintrayName = 'android-data-storage'
8 |
9 | publishedGroupId = 'xiaofei.library'
10 | libraryName = 'AndroidDataStorage'
11 | artifact = 'android-data-storage'
12 |
13 | libraryDescription = 'An easy-to-use and high-performance library for storing data in the Android system.'
14 |
15 | siteUrl = 'https://github.com/Xiaofei-it/AndroidDataStorage'
16 | gitUrl = 'https://github.com/Xiaofei-it/AndroidDataStorage.git'
17 |
18 | libraryVersion = '1.3.0'
19 |
20 | developerId = 'Xiaofei-it'
21 | developerName = 'Eric Zhao'
22 | developerEmail = 'xiaofei.it@gmail.com'
23 |
24 | licenseName = 'The Apache Software License, Version 2.0'
25 | licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
26 | allLicenses = ["Apache-2.0"]
27 | }
28 |
29 |
30 | android {
31 | compileSdkVersion 23
32 | buildToolsVersion "23.0.3"
33 |
34 | defaultConfig {
35 | minSdkVersion 8
36 | targetSdkVersion 23
37 | versionCode 3
38 | versionName "1.3.0"
39 | }
40 | buildTypes {
41 | release {
42 | minifyEnabled false
43 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
44 | }
45 | }
46 | defaultConfig {
47 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
48 | }
49 | }
50 |
51 | dependencies {
52 | compile fileTree(dir: 'libs', include: ['*.jar'])
53 | testCompile 'junit:junit:4.12'
54 | compile 'com.android.support:appcompat-v7:23.3.0'
55 | compile 'com.google.code.gson:gson:2.5'
56 | compile 'xiaofei.library:concurrent-utils:0.1.2'
57 | androidTestCompile 'com.android.support:support-annotations:23.3.0'
58 | androidTestCompile 'com.android.support.test:runner:0.5'
59 | androidTestCompile 'com.android.support.test:rules:0.5'
60 |
61 | }
62 |
63 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
64 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
65 |
--------------------------------------------------------------------------------
/android-data-storage/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/eleme/Downloads/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package xiaofei.library.datastorage;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/Test01.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2015-2016 Xiaofei
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package xiaofei.library.datastorage;
20 |
21 | import android.support.test.runner.AndroidJUnit4;
22 |
23 | import junit.framework.TestCase;
24 |
25 | import org.junit.Before;
26 | import org.junit.Test;
27 | import org.junit.runner.RunWith;
28 |
29 | /**
30 | * Created by Xiaofei on 16/6/16.
31 | */
32 | @RunWith(AndroidJUnit4.class)
33 | public class Test01 extends TestCase {
34 | int i = 0;
35 | @Before
36 | public void f() {
37 | System.out.println("Before");
38 | assertEquals(i, 0);
39 | i = 1;
40 | }
41 |
42 | @Test
43 | public void g() {
44 | System.out.println("Test");
45 | i = i + 1;
46 | assertEquals(i, 2);
47 | }
48 |
49 | @Test
50 | public void h() {
51 | ++i;
52 | assertEquals(i, 2);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/database/DbCacheConcurrency2Test.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2015-2016 Xiaofei
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package xiaofei.library.datastorage.database;
20 |
21 | import android.support.test.InstrumentationRegistry;
22 | import android.support.test.runner.AndroidJUnit4;
23 | import android.support.v4.util.Pair;
24 |
25 | import junit.framework.TestCase;
26 |
27 | import org.junit.After;
28 | import org.junit.Before;
29 | import org.junit.Test;
30 | import org.junit.runner.RunWith;
31 |
32 | import java.util.List;
33 | import java.util.concurrent.ExecutorService;
34 | import java.util.concurrent.Executors;
35 | import java.util.concurrent.atomic.AtomicInteger;
36 | import java.util.concurrent.locks.Condition;
37 | import java.util.concurrent.locks.Lock;
38 | import java.util.concurrent.locks.ReentrantLock;
39 |
40 | /**
41 | * Created by Xiaofei on 16/7/2.
42 | */
43 | @RunWith(AndroidJUnit4.class)
44 | public class DbCacheConcurrency2Test extends TestCase {
45 |
46 | private static final int MAX = 20;
47 |
48 | private DbCache dbCache;
49 |
50 | private ExecutorService executor = Executors.newFixedThreadPool(MAX);
51 |
52 | private AtomicInteger finish;
53 |
54 | private Lock lock = new ReentrantLock();
55 |
56 | private Condition condition = lock.newCondition();
57 |
58 | @Before
59 | public void init() {
60 | dbCache = DbCache.getInstance(InstrumentationRegistry.getContext());
61 | dbCache.clearTable();
62 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
63 | //singleton will stay there!!!
64 | }
65 |
66 | @Test
67 | public void insert() {
68 | finish = new AtomicInteger(0);
69 | for (int i = 0; i < MAX; ++i) {
70 | final int tmp = i;
71 | executor.execute(new Runnable() {
72 | @Override
73 | public void run() {
74 | final String threadName = Thread.currentThread().getName();
75 | for (int j = 0; j < MAX * MAX; ++j) {
76 | String value = "Haha" + threadName + " " + tmp;
77 | String id = threadName + " " + tmp + " " + j;
78 | dbCache.insertObject(value, id);
79 | //dbCache.clearCache();
80 | List> list = dbCache.getObjects(String.class, new xiaofei.library.datastorage.util.Condition() {
81 | @Override
82 | public boolean satisfy(String o) {
83 | return o.equals("Haha" + threadName + " " + tmp);
84 | }
85 | });
86 | assertEquals(list.size(), j + 1);
87 | }
88 | lock.lock();
89 | finish.getAndIncrement();
90 | condition.signalAll();
91 | lock.unlock();
92 | }
93 | });
94 | }
95 | try {
96 | lock.lock();
97 | while (finish.get() < MAX) {
98 | condition.await();
99 | }
100 | } catch (InterruptedException e) {
101 | e.printStackTrace();
102 | } finally {
103 | lock.unlock();
104 | }
105 | assertEquals(dbCache.getAllObjects(String.class).size(), MAX * MAX * MAX);
106 |
107 | }
108 |
109 | @Test
110 | public void insertAndClear() {
111 | for (int j = 0; j < MAX * MAX; ++j) {
112 | String value = "Haha";
113 | String id = "" + j;
114 | dbCache.insertObject(value, id);
115 | dbCache.clearCache();
116 | List> list = dbCache.getAllObjects(String.class);
117 | assertEquals(list.size(), j + 1);
118 | }
119 | }
120 |
121 |
122 | @After
123 | public void finish() {
124 | dbCache.clearTable();
125 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/database/DbCacheConcurrencyTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2015-2016 Xiaofei
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package xiaofei.library.datastorage.database;
20 |
21 | import android.support.test.InstrumentationRegistry;
22 | import android.support.test.runner.AndroidJUnit4;
23 |
24 | import junit.framework.TestCase;
25 |
26 | import org.junit.After;
27 | import org.junit.Before;
28 | import org.junit.Test;
29 | import org.junit.runner.RunWith;
30 |
31 | import java.util.concurrent.ExecutorService;
32 | import java.util.concurrent.Executors;
33 | import java.util.concurrent.atomic.AtomicInteger;
34 | import java.util.concurrent.locks.Condition;
35 | import java.util.concurrent.locks.Lock;
36 | import java.util.concurrent.locks.ReentrantLock;
37 |
38 | /**
39 | * Created by Xiaofei on 16/6/17.
40 | */
41 | @RunWith(AndroidJUnit4.class)
42 | public class DbCacheConcurrencyTest extends TestCase {
43 |
44 | private static final int MAX = 50;
45 |
46 | private DbCache dbCache;
47 |
48 | private ExecutorService executor = Executors.newFixedThreadPool(MAX);
49 |
50 | private AtomicInteger finish;
51 |
52 | private Lock lock = new ReentrantLock();
53 |
54 | private Condition condition = lock.newCondition();
55 |
56 | @Before
57 | public void init() {
58 | dbCache = DbCache.getInstance(InstrumentationRegistry.getContext());
59 | dbCache.clearTable();
60 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
61 | //singleton will stay there!!!
62 | }
63 |
64 | @Test
65 | public void insert() {
66 | finish = new AtomicInteger(0);
67 | for (int i = 0; i < MAX; ++i) {
68 | final int tmp = i;
69 | executor.execute(new Runnable() {
70 | @Override
71 | public void run() {
72 | for (int j = 0; j < MAX * MAX; ++j) {
73 | //空格很重要
74 | dbCache.insertObject("Haha", Thread.currentThread().getName() + " " + tmp + " " + j);
75 | }
76 | lock.lock();
77 | finish.getAndIncrement();
78 | condition.signalAll();
79 | lock.unlock();
80 | }
81 | });
82 | }
83 | try {
84 | lock.lock();
85 | while (finish.get() < MAX) {
86 | condition.await();
87 | }
88 | } catch (InterruptedException e) {
89 | e.printStackTrace();
90 | } finally {
91 | lock.unlock();
92 | }
93 | assertEquals(dbCache.getAllObjects(String.class).size(), MAX * MAX * MAX);
94 |
95 | }
96 |
97 |
98 |
99 | @Test
100 | public void insertAndDelete() {
101 | finish = new AtomicInteger(0);
102 | for (int i = 0; i < MAX; ++i) {
103 | final int tmp = i;
104 | executor.execute(new Runnable() {
105 | @Override
106 | public void run() {
107 | for (int j = 0; j < MAX * MAX; ++j) {
108 | //String id = Thread.currentThread().getName() + j;
109 | String id = Thread.currentThread().getName() + " " + tmp + " " + j;
110 | dbCache.insertObject("Haha", id);
111 | dbCache.deleteObject(String.class, id);
112 | }
113 | lock.lock();
114 | finish.getAndIncrement();
115 | condition.signalAll();
116 | lock.unlock();
117 | }
118 | });
119 | }
120 | try {
121 | lock.lock();
122 | while (finish.get() < MAX) {
123 | condition.await();
124 | }
125 | } catch (InterruptedException e) {
126 | e.printStackTrace();
127 | } finally {
128 | lock.unlock();
129 | }
130 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
131 |
132 | }
133 |
134 | @After
135 | public void finish() {
136 | //dbCache.clearTable();
137 |
138 | //sleep(3000);
139 | //dbCache.deleteAllObjects(String.class);
140 | //assertEquals(dbCache.getAllObjects(String.class).size(), 0);
141 | /**
142 | * 这种写法在insert测试中,立马从数据库读,能读到所有数据。也就是说数据库根本还没执行。
143 | * 貌似sleep没什么用
144 | * 所以deleteAllObjects不应该remove!!!
145 | * 跟clearTable一样!
146 | */
147 |
148 |
149 | //dbCache.deleteAllObjects(String.class);
150 | dbCache.clearTable();
151 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
152 | }
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/database/DbCacheExtremelyLongObjectTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2015-2016 Xiaofei
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package xiaofei.library.datastorage.database;
20 |
21 | import android.support.test.InstrumentationRegistry;
22 | import android.support.test.runner.AndroidJUnit4;
23 | import android.support.v4.util.Pair;
24 |
25 | import junit.framework.TestCase;
26 |
27 | import org.junit.After;
28 | import org.junit.Before;
29 | import org.junit.Test;
30 | import org.junit.runner.RunWith;
31 |
32 | import java.util.List;
33 | import java.util.concurrent.ExecutorService;
34 | import java.util.concurrent.Executors;
35 | import java.util.concurrent.atomic.AtomicInteger;
36 | import java.util.concurrent.locks.Condition;
37 | import java.util.concurrent.locks.Lock;
38 | import java.util.concurrent.locks.ReentrantLock;
39 |
40 | /**
41 | * Created by Xiaofei on 16/7/2.
42 | */
43 | @RunWith(AndroidJUnit4.class)
44 | public class DbCacheExtremelyLongObjectTest extends TestCase {
45 |
46 | private static final int LENGTH = 10000000;
47 |
48 | private DbCache dbCache;
49 |
50 | @Before
51 | public void init() {
52 | dbCache = DbCache.getInstance(InstrumentationRegistry.getContext());
53 | dbCache.clearTable();
54 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
55 | }
56 |
57 | @Test
58 | public void test() {
59 | StringBuilder sb = new StringBuilder();
60 | for (int i = 0; i < LENGTH; ++i) {
61 | sb.append("a");
62 | }
63 | dbCache.insertObject(sb.toString(), "key");
64 | dbCache.clearCache();
65 | String s = dbCache.getObject(String.class, "key");
66 | assertEquals(s.length(), LENGTH);
67 | }
68 |
69 |
70 | @After
71 | public void finish() {
72 | dbCache.clearTable();
73 | assertEquals(dbCache.getAllObjects(String.class).size(), 0);
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/android-data-storage/src/androidTest/java/xiaofei/library/datastorage/database/DbCacheTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2015-2016 Xiaofei
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package xiaofei.library.datastorage.database;
20 |
21 | import android.support.test.InstrumentationRegistry;
22 | import android.support.test.runner.AndroidJUnit4;
23 | import android.support.v4.util.Pair;
24 |
25 | import junit.framework.TestCase;
26 |
27 | import org.junit.Before;
28 | import org.junit.Test;
29 | import org.junit.runner.RunWith;
30 |
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | import xiaofei.library.datastorage.util.Condition;
35 |
36 | /**
37 | * Created by Xiaofei on 16/6/16.
38 | */
39 | @RunWith(AndroidJUnit4.class)
40 | public class DbCacheTest extends TestCase {
41 | private DbCache dbCache;
42 | @Before
43 | public void init() {
44 | dbCache = DbCache.getInstance(InstrumentationRegistry.getContext());
45 | dbCache.clearTable();
46 | //singleton will stay there!!!
47 | }
48 |
49 | @Test
50 | public void storeAndLoad() {
51 | dbCache.insertObject("ok", "1");
52 | dbCache.clearCache();
53 | String str = dbCache.getObject(String.class, "1");
54 | assertEquals(str, "ok");
55 |
56 | dbCache.clearCache();
57 | List