数据持久化的几种方式
本章学习了三种存储数据的方式。
- 文件操作
- SharedPreferences存储键值对
- SQLite数据库操作
SharedPreferences
如果有一堆键值对需要存储,那么
SharedPreferences
最合适不过了。
获取SharedReferences对象
有几种方法,记录两种常用的
-
Contex.getSharedPreferences()
方法。这里有两个参数,第一个是存放SharedPreferences文件的文件名,如果文件不存在会自动创建一个。第二个参数是指定操作模式:MODE_PRIVATE
代表只有当前应用程序才可以对这个文件进行读写。MODE_MULTI_PROCESS
一般用于会有多个进程对同一个文件进行读写的情况。Context context = getActivity(); SharedPreferences sharedPref = context.getSharedPreferences( getString(R.string.preference_file_key), Context.MODE_PRIVATE);
-
Activity
类中的getPreferences()
方法。只接收操作模式参数,因为它会自动以当前类的名字创建文件。SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
写数据到Shared Preferences
调用SharedPreferences
的edit()方法来获取一个SharedPreferences.Editor
对象,向Editor中添加数据,就像putInt(),putString()这样,然后利用commit()提交;
SharedPreferences.Editor editor = SharedPreferences.edit();
//put方法第一个参数是Key,第二个参数是value
editor.putStirng("name","Jack");
editor.commit();
从Shared Preferences
直接调用SharedPreferences
的get方法,就像put差不多。
Stirng name;
sharedPref.getString("name",name);
Files
保存数据到文件
愚人节快乐啊。Talk is cheap,show you the code :
String FILENAME = "hello_file";
String data = "hello file";
FileOutputStream outputStream = openFileOutput(FILENAME,
Context.MOIDE_PRIVATE);
outputStream.write(data.getBytes());
outputStream.close;
说是这么说还是要解释一下啊哈哈。
Context
提供了一个openFileOutput()
的方法来返回一个FileOutputStream
对象,然后就可以对其操作啦。java.io掌握了,这里也就没问题了。
从文件中读取数据
同上,
Context
提供的openFileInput()
方法返回一个FileInputStream
对象,然后操作就可以了。
SQLite
要操作数据库,就需要我们去继承
SQLiteOpenHelper
这个抽象类来创建自己的数据库帮助类,进而完成对数据库的各种操作。SQLite拥有的数据类型很简单,
integer
表示整型,real
表示浮点型,text
表示文本类型,blob
表示二进制类型。
实现自己的SQLiteOpenHelper类
public class TestDbOpenHelper extends SQLiteOpenHelper {
//create table 语句
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text )";
//为提示消息创建一个context
Context mContext;
public TestDbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,int version) {
super(context,name,factory,version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//在onCreate方法中进行表的创建或者其他数据库初始化操作
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,"Create table BOOK!",Toast.LENGTH_SHORT).show();
}
//调用构造方法时根据版本号的大小来确定是否进行数据库更新,如果版本号比当前版本号新则执行此方法里的操作
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
创建数据库
当你创建了一个SQLiteOpenHelper对象,然后调用
getWritableDatabase()
或者getReadableDatabase()
方法时,如果数据库不存在,则会创建一个数据库。对于Helper对象的构造方法的参数:Context context, String name, SQLiteDatabase.CursorFactory factory,int version。第一个context是操作数据库的对象,第二个name是数据库的名字,后面的factory是可以允许我们获取cursor,后面查询会用到,version是版本号,用于更新数据库操作。
添加数据
//添加数据操作很简单,就是向database里插入一条数据,这条数据以ContentValues的形式添加>
SQLiteDatabase database = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//装一条数据
values.put("name","The art of code");
values.put("author","hahaha");
values.put("pages",454);
values.put("price", 100);
database.insert("Book", null, values);
values.clear();
更新数据
//更新数据用到了database的update方法
SQLiteDatabase database = myDatabaseHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",10.9);
database.update("Book", values, "name = ?", new String[]{"The art of code"});
values.clear();
database.update();
这里有四个参数,第一个是表名字,第二个是要更新的那条数据,第三四个参数对应了SQL语句里的where语句。
删除数据
SQLiteDatabase database = myDatabaseHelper.getWritableDatabase();
database.delete("Book", "pages > ?", new String[]{"400"});
database.delete()
第一个参数是表名,第二第三个参数指定约束,不指定则默认删除这个表的所有行。
查询数据
SQLiteDatabase database = myDatabaseHelper.getWritableDatabase();
Cursor cursor = database.query("Book",null,null,null,null,null,null);
if (cursor.moveToFirst()){
do {
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();
query()方法
query方法有很多参数,源于查询这个功能比较复杂...
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
table
: 指定查询的表名
columns
: 指定查询的列名
selection
: 指定where的约束条件
selectionArgs
: 为where中的占位符提供具体的值
groupBy
: 指定需要group by 的列
having
: 对group by后的结果进一步约束
orderBy
: 指定对查询结果的排序方式
query方法会返回一个
Cursor
对象,查询到的对象需要从这个对象里面取出。利用其moveToNext()
移动,然后getInt()
获取这一行的某一列的数据,get
方法里传入的是`cursor.getColumnIndex("pages"),是对于这一列数据的一个位置索引,用来定位这个数据在哪一列。
使用SQL操作数据库
除了用提供的API对数据库进行操作以外,我们还可以使用SQL语句来对数据库进行操作。
//添加数据
db.execSQL("insert into Book {name,author,pages,price) valuese(?,?,?,?)",
new String[] {"hha","d“,"100","10"} );
//更新数据
db.execSQL("update Book set price = ? where name = ?",
new String[] {"11","hha"} );
//删除数据
db.execSQL("delete from Book where pages > ?",new String {"500"});
//查询数据
db.rawQuery("select * from Book",null);
使用事务
//开启事务
db.beginTransaction();
//在异常捕获的代码块中去执行事务操作
try {
//do something to db here.
} catch (Exception e) {
//捕获异常
e.printStackTrace();
} finally {
//如果没有异常发生
db.endTransaction()'
}
升级数据库的最佳写法
在onUpgrade()方法里对版本号进行判断来确定要执行的SQL语句。
switch (oldVersion){
case 1:
database.execSQL(CREATE_CATEGORY);
case 2:
database.execSQL("alert table Book add column category_id integer");
}
switch语句里是没有break的,这样就可以让版本不同的用户是按升级顺序执行对数据库的每一步操作。
总结
这章总结了数据存储的三种方式。
文件存储,SharedPreferences,数据库存储。
文件存储文本数据或者二进制数据,SharedPreferences存储键值对,数据库存储关系型数据。
要根据实际需要选择存储的方式。