Persisting Data to the Device
Persisting Data to the Device
Overview
The Android framework offers several options and strategies for persistence:
- Shared Preferences - Easily save basic data as key-value pairs in a private persisted dictionary.
- Local Files - Save arbitrary files to internal or external device storage.
- SQLite Database - Persist data in tables within an application specific database.
- ORM - Describe and persist model objects using a higher level query/update syntax.
Use Cases
Each storage option has typical associated use cases as follows:
- Shared Preferences - Used for app preferences, keys and session information.
- Local Files - Often used for blob data or data file caches (i.e disk image cache)
- SQLite Database - Used for complex local data manipulation or for raw speed
- ORM - Used to store simple relational data locally to reduce SQL boilerplate
Note that a typical app utilizes all of these storage options in different ways.
Shared Preferences
Settings can be persisted for your application by using SharedPreferences to persist key-value pairs.
To retrieve an existing username key from your Shared Preferences, you can type:
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(this);
String username = pref.getString("username", "n/a");
SharedPreferences can be edited by getting access to the Editor instance:
SharedPreferences pref =
PreferenceManager.getDefaultSharedPreferences(this);
Editor edit = pref.edit();
edit.putString("username", "billy");
edit.putString("user_id", "65");
edit.commit();
Local Files
Android can read/write files to internal as well as external storage. Applications have access to an application-specific directory where preferences and sqlite databases are also stored. Every Activity has helpers to get the writeable directory. File I/O API is a subset of the normal Java File API.
Writing files is as simple as getting the stream using openFileOutput method] and writing to it using a BufferedWriter:
// Use Activity method to create a file in the writeable directory
FileOutputStream fos = openFileOutput("filename", MODE_WORLD_WRITEABLE);
// Create buffered writer
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
writer.write("Hi, I'm writing stuff");
writer.close();
Reading the file back is then just using a BufferedReader and then building the text into a StringBuffer:
BufferedReader input = null;
input = new BufferedReader(
new InputStreamReader(openFileInput("myfile")));
String line;
StringBuffer buffer = new StringBuffer();
while ((line = input.readLine()) != null) {
buffer.append(line + "\n");
}
String text = buffer.toString();
You can also inspect and transfer files to emulators or devices using the DDMS File Explorer perspective which allows you to access to filesystem on the device.
SQLite
For maximum control, developers can use SQLite directly by leveraging the SQLiteOpenHelper for executing SQL requests and managing a local database:
public class TodoItemDatabase extends SQLiteOpenHelper {
public TodoItemDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// These is where we need to write create table statements.
// This is called when database is created.
@Override
public void onCreate(SQLiteDatabase db) {
// SQL for creating the tables
}
// This method is called when database is upgraded like
// modifying the table structure,
// adding constraints to database, etc
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
// SQL for upgrading the tables
}
}
Check out our managing databases with SQLiteOpenHelper guide for a more detailed look at working with SQLite. In many cases, rather than interacting with SQL directly, Android apps can leverage one of the many available higher-level ORMs (object relational mappers) to persist Java models to a database table as shown below. If needed, we can also access the SQLite database for debugging.
There are a handful of interesting SQLiteOpenHelper wrappers which reduce the level of code written including the following libraries:
- Cupboard - Original take on SQL wrapper
- SQLBrite - Square's take on a SQL wrapper
- StorIO - Popular new take on a light SQL wrapper
Each of these provide a thin layer of abstraction on SQLiteOpenHelper. For a more comprehensive abstraction, we can use mapping engines that automatically create model objects based on SQL data as outlined below.
Object Relational Mappers
Instead of accessing the SQLite database directly, there is no shortage of higher-level wrappers for managing SQL persistence. There are many popular ORMs for Android, but one of the easiest to use is ActiveAndroid (cliffnotes). Here's a few alternatives as well:
- DBFlow - Newer, light syntax, fast (cliffnotes)
- SugarORM - Very easy syntax, uses reflection to infer data (cliffnotes)
- Siminov - Another viable alternative syntax
- greenDAO - Slightly different take (DAO vs ORM)
- ORMLite - Lightweight and speed is prioritized
- JDXA - Simple, non-intrusive, flexible
For this class, we selected ActiveAndroid. With ActiveAndroid, building models that are SQLite backed is easy and explicit using annotations. Instead of manually creating and updating tables and managing SQL queries, simply annotate your model classes to associate fields with database columns:
@Table(name = "Users")
public class User extends Model {
@Column(name = "Name")
public String name; @Column(name = "Age")
public int age; // Make sure to define this constructor (with no arguments)
// If you don't querying will fail to return results!
public User() {
super();
} // Be sure to call super() on additional constructors as well
public User(String name, int age){
super();
this.name = name;
this.age = age;
}
}
Inserting or updating objects no longer requires manually constructing SQL statements, just use the model class as an ORM:
User user = new User();
user.name = "Jack";
user.age = 25;
user.save();
// or delete easily too
user.delete();
ActiveAndroid queries map to SQL queries and are built by chaining methods.
List<User> users = new Select()
.from(User.class).where("age > ?", 25)
.limit(25).offset(0)
.orderBy("age ASC").execute();
This will automatically query the database and return the results as a List for use. For more information, check out ourActiveAndroid Guide for links to more resources and answers to common questions. As needed, we can also access the SQLite database for debugging.
References
- http://developer.android.com/guide/topics/data/data-storage.html
- http://developer.android.com/training/basics/data-storage/index.html
- http://mobile.tutsplus.com/tutorials/android/data-management-options-for-android-applications/
- http://developer.android.com/reference/android/content/SharedPreferences.html
// Use Activity method to create a file in the writeable directory
FileOutputStream fos = openFileOutput("filename", MODE_WORLD_WRITEABLE);
// Create buffered writer
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));
writer.write("Hi, I'm writing stuff");
writer.close();
Persisting Data to the Device的更多相关文章
- [Node.js] Level 7. Persisting Data
Simple Redis Commands Let's start practicing using the redis key-value store from our node applicati ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-006Spring-Data的运行规则(@EnableJpaRepositories、<jpa:repositories>)
一.JpaRepository 1.要使Spring自动生成实现类的步骤 (1)配置文件xml <?xml version="1.0" encoding="UTF- ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-005Spring-Data-JPA例子的代码
一.结构 二.Repository层 1. package spittr.db; import java.util.List; import org.springframework.data.jpa. ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-002设置JPA的EntityManagerFactory(<persistence-unit>、<jee:jndi-lookup>)
一.EntityManagerFactory的种类 1.The JPA specification defines two kinds of entity managers: Applicatio ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-004JPA例子的代码
一.结构 二.Repository层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-003编写JPA-based repository( @PersistenceUnit、 @PersistenceContext、PersistenceAnnotationBeanPostProcessor)
一.注入EntityManagerFactory的方式 package com.habuma.spittr.persistence; import java.util.List; import jav ...
- SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-001-使用Hibernate(@Inject、@EnableTransactionManagement、@Repository、PersistenceExceptionTranslationPostProcessor)
一.结构 二.Repository层 1. package spittr.db; import java.util.List; import spittr.domain.Spitter; /** * ...
- Persisting iOS Application Data in SQLite Database Using FMDB
In previous articles we have utilized NSUserDefaults and .NET web services to persist iPhone data. N ...
- 部署samba服务之后,在客户端用挂载访问的方式,错误信息:mount: block device //192.168.1.108/mysqldata is write-protected, mounting read-only mount: cannot mount block device //192.168.1.108/mysqldata read-only
部署samba服务之后,在客户端用挂载访问的方式,错误信息:mount: block device //192.168.1.108/mysqldata is write-protected, moun ...
随机推荐
- 倍增法求LCA
倍增法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 倍增法是通过一个数组来实现直接找到一个节点的某个祖先,这样我们就可 ...
- SpringMVC(8) - 处理器映射
在以前的Spring版本中,用户需要在Web应用程序上下文中定义一个或多个HandlerMapping bean,以将传入的Web请求映射到适当的处理器.通过引入带注解的控制器,就不需要像之前那样定义 ...
- 逆序对数列(BZOJ 2431)
题目描述 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样 ...
- python学习之- 内置函数
内置方法:1:abs():取绝对值2:all():当可迭代对象里所有均为真时结果为真. all([1,2,3])3:any():当可迭代对象里任意一个数据为真结果即为真.any([0,1,2])4:a ...
- BZOJ——2563: 阿狸和桃子的游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2563 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: ...
- Java实验——输出一个数组里面连续子数组最大的和(二)文件操作
在本周的练习中,主要是对上周的实验进行健壮性的完善,即在所能考虑到的情况之中,尽量使自己的程序能够正常地运行. 在上周的实验中,我已经是在编程过程中考虑到用户输入的错误类型的问题,所以这一方面并没有多 ...
- html5 拖拽元素
利用html5实现元素的拖拽,让拖动元素在指定的容器中拖动. 注意点:1.被拖元素要设置拖动属性.draggable="true" 2.容器元素要设置阻止默认事件处理 实现效果图如 ...
- openstack ocata 的cell 和 placement api
The Ocata openstack just released recently. The official docs is not very stable yet. Some key steps ...
- 你创建线程池最好分为两种线程池,io密集型线程池,或者cpu密集型线程池
你创建线程池最好分为两种线程池,io密集型线程池,或者cpu密集型线程池. 否则,如果只用一个线程池的话,不管是iO密集的线程,或者cpu消耗大的都放在同一个线程池的话,会发生线程池被撑满的情况
- 《gis空间分析及应用案例解析》培训总结
<gis空间分析及应用案例解析>培训总结 来源:常德水情 作者:唐校准 发布日期:2014-01-02 2013年12月2630日由中国科学院计算技术研究所教育中心组织的< ...