本篇主要涉及Android中的数据持久化技术。
不对存储内容进行任何格式化处理,原封不动的保存到文件中。适合存储一些简单的文本数据或二进制数据。
openFileOutput()
方法,接收两个参数:(文件名, 操作模式)。/data/data/<package name>/files/
目录下;write
方法将数据写入文件。public void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out =openFileOutput("data", Context.MODE_PRIVATE); // 获取FileOutputStream对象
writer = new BufferedWriter(new OutputStreamWriter(out); // 构建BufferedWriter对象
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close()
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
openFileInput(文件名)
方法。public String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data"); // 获取FileInputStream对象
reader = new BufferedReader(new InputStreamReader(in)); // 构建BufferedReader对象
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line); // 逐行读取,若内容不为空添加到StringBuilder中
}
} catch (IOException e) {
e.printStackTrace;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
采用键值对的方式存储数据,支持多种不同的数据类型存储,使用XML格式来管理数据的。
getSharePregerences(文件名, 操作模式)
方法。 /data/data/<package name>/shared_prefs/
目录下getPreferences(操作模式)
方法。 getDeafaultSharedPreferences(context)
方法。 edit()
方法来获取一个SharedPreferences.Editor对象;putString()
、putBoolean()
等方法;apply()
方法提交数据。SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.apply();
使用 getSring()
、getBoolean()
等方法,接收两个参数:(键, 默认值)。
SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "age is " + age);
Log.d("MainActivity", "married is " + married);
适合存储大量复杂的关系型数据。
onCreate()
、onUpgrade()
方法来创建和升级数据库。getReadableDatabase()
、getWritableDatabase()
用于创建或打开现有数据库,并返回一个可进行读写操作的对象。/data/data/<package name>/databases/
目录下。public class MyDatabaseOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key antoincrement, " // 设置为主键,自增长
+ "author text" // text表示文本类型
+ "price real, " // real表示浮点型
+ "pages integer, " // integer表示整型
+ "name text)";
private Context mContext;
public MyDataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = (Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
}
}
onUpgrade()
中执行DROP语句,再调用 onCreate()
方法重新创建;onUpgrade()
能够执行。@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category"); // 若创建表时发现表已存在,需要删除掉,否则会报错
onCreate(db);
}
使用SQLiteDatabase的 insert()
方法,接收三个参数:(要添加数据的表名, null, ContentValues对象)
put()
方法重载用于向其中添加数据,传入 (列名, 待添加数据) 即可。SQLiteDatabase db = dbHelper.getWritableDataBase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
db.insert("Book", null, values); // 插入第一条数据
values.clear();
// 开始组装第二条数据
...
db.insert("Book", null, valuse); // 插入第二条数据
使用 update()
方法,接收四个参数:(表名, ContentValues对象, 约束语句, 字符串数组)。
new String[] {"The Da Vinci Code"}
。SQLiteDatabase db = dbHelper.getWritaberDatabase();
ContentValues values = new ContentValues();
values.put("price", 10.99);
db.update("Book", values, "name = ?", new String[] {"The Da Vinci Code"}); // 更新书名为"The Da Vinci Code"的数据
使用 delete()
方法,接收三个参数:(表名, 约束语句, 字符串数组)。
db.delete("Book", "pages > ?", new String[] {"500"}); // 删除页数超过500的书
query()
方法,最短的方法重载接收七个参数;moveToFirst()
将数据指针移动到第一行位置(返回True表示移动成功数据不为空);getColumnIndex()
方法获取到某一列在表中对应的位置索引,将其传入对应取值方法中就可以读取到数据了;colse()
方法关闭Cursor。query()方法参数 | 对应SQL部分 | 描述 |
---|---|---|
table | from table_name | 指定查询的表名 |
columns | select column1, column2 | 指定查询的列名 |
selection | where column = value | 指定where的约束条件 |
selectionArgs | - | 为where中的占位符提供具体值 |
groupBy | group by column | 指定需要group by的列 |
having | having column = value | 对group by后的结果进一步约束 |
orderBy | order by column1,column2 | 指定查询结果的排序方式 |
// 查询Book表中的所有数据
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
// 遍历Cursor对象,取出数据并打印
String name = cursor.getString(Cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity", "book name is " + name);
Log.d("MainActivity", "book author is " + author);
Log.d("MainActivity", "book pages is " + pages);
Log.d("MainActivity", "book price is " + price);
} while (cursor.moveToNext());
}
cursor.close();
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] {"The Da Vinci Code", "Dan Brown", "454", "16.96"});
db.execSQL("update Book set price = ? where name = ?", new String[] {"10.99", "The Da Vinci Code"});
db.execSQL("delete from Book where pages > ?", new String[] {"500"});
db.rawQuery("select * from Book", null);
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并对常用数据库功能进行了封装。
compile 'org.litepal.android:core:1.4.1'
<?xml version = "1.0" encoding="utf-8"?>
<litepal>
<!-- 数据库名 -->
<dbname value="BookStore" ></dbname>
<!-- 数据库版本号 -->
<version value="1" ></version>
<!-- 指定所有映射模型 -->
<list>
</list>
</litepal>
<application android:name="org.litepal.LitePalApplication" ...>
...
</application>
<mapping>
标签;Connector.getDatabase()
创建数据库。/** 根据Book表的内容定义Book类 */
public class Book{
private int id;
private String author;
private double price;
private int pages;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
... //生成各个字段对应的getter和setter方法
}
<!-- 添加到映射模型列表中 -->
<list>
<mapping class="com.example.litepaltest.Book"></mapping>
</list>
@Override
public void onClick(View v) {
Connector.getDatabase(); // 创建数据库
}
更改想要修改的任何内容,然后将版本号加1即可。升级会保留之前表中的所有数据。
创建出模型实例(要进行CRUD操作模型类必须继承字DataSupport类),调用set方法将所有要存储的数据设置好,最后调用 save()
方法即可。
public class Book extends DataSupport {
...
}
Book book = new Book();
book.setName("The Da Vinci Code");
book.setAuthor("Dan Brown");
book.setPages(454);
book.setPrice(16.96);
book.setPress("UnKnow");
book.save():
updateAll()
方法执行更新操作(updateAll中可以指定约束条件)。setToDefault()
方法。/** 将书名为The Lost Symbol并且作者是Dan Brown的书价格更新为14.95,出版社更新为Anchor */
Bool book = new Book();
book.setPrice(14.95);
book.setPress("Anchor");
book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan Brown");
/** 将所有书页更新为0(默认值) */
Book book = new book;
book.setToDefault("pages");
book.updateAll();
delete()
方法。DataSupport.deleteAll()
方法,接收三个参数:(要删除数据的表名, 约束条件, 占位符内容)/** 删除Book表中价格低于15的书 */
DataSupport.deleteAll(Book.class, "price < ?", "15");
findAll()
方法,返回值为对应类型的List集合。List<Book> books = DataSupport.finAll(Book.class);
for (Book book : books) {
Log.d("MainActivity", "book name is " + book.getName());
Log.d("MainActivity", "book author is " + book.getAuthor());
Log.d("MainActivity", "book pages is " + book.getPages());
Log.d("MainActivity", "book price is " + book.getPrice());
Log.d("MainActivity", "book press is " + book.getPress());
}
findFirst()
、findLast()
分别查询第一条和最后一条数据.方法 | 对应SQL部分 | 描述 |
---|---|---|
select() | select | 指定查询哪几列数据 |
where() | where | 指定查询的约束条件 |
order() | order by | 指定结果的排序方式(desc降序,asc或不写为升序) |
limit() | limit | 指定查询结果的数量 |
offset() | limit | 指定查询结果的偏移量 |
/** 查询Book表中第11~20条页数大于400的name、author、pages这三列数据,并将结果按页数升序排列 */
List<Book> books = DataSupport.select("name", "author", "pages")
.where("pages > ?", "400")
.order("pages") // 默认为asc升序
.limit(10) // 只查前10条
.offset(10) // 偏移10个位置
.find(Book.class);
DataSupport.findBySQL(SQL语句, 占位符的值)
,返回一个Cursor对象。Cursor c = DataSupport.findBySQL("select * from Book where pages > ? and price < ?", "400", "20");