详解持久化技术
详解持久化技术
持久化技术简介
持久化技术就是将内存中的临时数据保存到储存设备中,即使在手机或电脑关机的情况下,这些数据仍然不会丢失,保存在内存中的数据是瞬时状态,保存在设备中的数据则是持久状态的;持久化数据就是让数据在瞬时与持久状态之间进行转换的。android主要提供了三种方法:文件储存;SharePreference储存;数据库储存。
文件储存
将数据保存到文件中
Context类中提供了一个openFileOutput方法,可以用于将数据储存到指定文件中。这个方法接收两个参数,第一个参数是文件名,文件创建的就是这个名称,
这里输入的文件名不包含路径,因为所有的文件都是默认储存到/data/data/<packagename>/file/
目录下的。第二个参数是文件的操作模式,有两种操作模式,MODE_PRIVATE(默认模式)表示当指定相同的文件名时会覆盖之前的信息;MODE_APPEND表示如果文件已存在则添加数据,否则新建文件
openFileOutput()返回一个FileOutputStream对象,得到了这个对象后用java流的方式将数据写入到文件中:
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=findViewById(R.id.edit);
}
@Override
protected void onDestroy() {
super.onDestroy();
String text=editText.getText().toString();
save(text);
}
public void save(String text){
FileOutputStream out =null;
BufferedWriter writer=null;
try {
out=openFileOutput("data", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(text);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (writer !=null){
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
输入数据之后点击返回按钮,会在文件中找到名为data的文件,里面就是保存的数据。
读取文件中的数据
Context还提供了一个openFileInput()方法,用于从文件中读取数据,这个方法接收一个参数:要读取的文件的文件名,然后系统会自动加载这个文件,并返回一个FileInputStream对象,得到这个对象后通过java流的方式读取出来。
public String read(){
FileInputStream in=null;
BufferedReader reader=null;
StringBuilder context=new StringBuilder();
try {
in=openFileInput("data");
reader=new BufferedReader(new InputStreamReader(in));
String line="";
while((line=reader.readLine())!=null){
context.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return context.toString();
}
SharedPreferences储存
SharedPreferences储存是通过键值对的方式来存储数据的,支持多种数据类型储存
将数据储存到SharedPreferences
首先要获取到SharedPreferences对象,android提供了三种方法用于获取。
SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/
目录下的xml文件
-
Context类中的getSharedPreferences方法
这个方法接收两个参数,第一个参数用于指定SharePreferences文件的名称,如果指定的文件不存在则会创建一个;第二个参数用于操作模式,可以写MODE_PRIVATE这一模式(其他模式均已废弃),表示只有当前的应用程序才能对文件进行读写,和直接传入0的效果是一样的。
-
Activity类中的getPreferences方法
这个方法和Context中的getSharedPreferences()方法很相似,只接收一个操作模式参数,这个方法会自动将当前活动的类名作为SharedPreferences的文件名
-
PreferenceManager类中的getDefaultSharePreferences方法
这是一个静态方法,接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。得到了Sharedpreferences对象之后,就开始向Shared_Preferences文件中储存数据,分三步实现:
-
调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象;
-
向SharedPreferences对象中添加数据;
-
调用apply()方法将储存的数据提交,从而完成数据存储操作;
-
点击事件储存数据
SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name","makabaka");
editor.putInt("age",20);
editor.putBoolean("married",true);
editor.apply();
Sharedferences中读取数据
put换成get差不多了
SharedPreferences preferences=getSharedPreferences("data",MODE_PRIVATE);
String name=preferences.getString("name","");
int age=preferences.getInt("age",0);
Boolean married=preferences.getBoolean("married",false);
Toast.makeText(this, name+age+married, Toast.LENGTH_SHORT).show();
SQLite数据库
创建数据库
android提供了一个SQLiteOpenHelper帮助类,这是一个抽象类,所以要使用这个类的话需要创建一个自己的帮助类来继承它。其中有两个抽象方法,onCreate()和onUpgrade(),我们需要重写这两个方法,分别在这两个方法中实现创建,升级数据库的方法。
SQLiteOpenHelper提供了两个很重要的实例方法,getReadableDatabase()和getWritableDatabase(),这两个方法都可以创建或打开一个现有数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase返回对象将以只读的方式打开数据库,而getWritableDatabase()方法则将出现异常。
- 新建MySqlLiteHelper继承SQLiteOpenHelper,重写onCreate()和onUpgrade()方法;
- 重写构造函数;(第一个参数:context;第二个参数:数据库名;第三个参数:一般null,第四个参数:当前数据库的版本号,可用于对数据库的升级)
- 获取helper对象,新建Constant表
SQLiteOpenHelper:
public class MySqlLiteHelper extends SQLiteOpenHelper {
public MySqlLiteHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public MySqlLiteHelper(Context context){
super(context,Constant.DATABASE_NAME,null,Constant.DATABASE_VERSION);
}
//创建数据库时调用这个的方法
@Override
public void onCreate(SQLiteDatabase db) {
}
//数据库升级时调用的方法
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onOpen(SQLiteDatabase db) {
Log.i(TAG, "open");
}
}
DbManger:
public class DbManger {
//获取helper对象
private static MySqlLiteHelper helper;
public static MySqlLiteHelper getIntance(Context context){
if (helper==null){
helper=new MySqlLiteHelper(context);
}
return helper;
}
}
创建数据库:
private MySqlLiteHelper helper;
helper= DbManger.getIntance(this);
SQLiteDatabase db=helper.getReadableDatabase();
//创建表,也可以放在SQLiteOpenHelper中的onCreate方法中
String sql = "create table "+Constant.TABLE_NAME+" ("+Constant._ID+" Integer primary key,"+Constant.NAME+" varchar(20),"+Constant.AGE+" Integer(20))";
db.execSQL(sql);//执行sql语句
升级数据库
onUpgrade()方法是用于对数据库进行升级的,想调用这个方法就需要升级数据库;之前构造函数的第四个参数就是就是数据库版本,之前传入的是1,只用传入一个比1大的数字,就能让onUpgrade()方法执行了
增删改
adroid提供了无需sql语句进行数据库操作的方法:
helper= DbManger.getIntance(this);
SQLiteDatabase db=helper.getReadableDatabase();
switch (view.getId()){
case R.id.zeng:
/**
* insert(String table, String nullColumnHack, ContentValues values)
* String table 表示插入数据表的名称
* String nullColumnHack
* ContentValues values 键为string类型的hashmap集合
* 返回lang表示插入数据列数
*/
// SQLiteDatabase db=helper.getReadableDatabase();
ContentValues values=new ContentValues();
values.put(Constant._ID,3);
values.put(Constant.NAME,"张三");
values.put(Constant.AGE,29);
long result=db.insert(Constant.TABLE_NAME,null,values);
if (result>0){
Toast.makeText(this, "成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
}
db.close();
break;
case R.id.gai:
helper= DbManger.getIntance(this);
db=helper.getReadableDatabase();
/**
* update(String table, ContentValues values, String whereClause, String[] whereArgs)
* String table表示插入数据表的名称
*ContentValues values键为string类型的hashmap集合
*String whereClause 修改条件
*String[] whereArgs 修改条件的占位符
*/
ContentValues cv=new ContentValues();
cv.put("name","小爱");//第一个为修改的字段名,第二个为修改后的值
int count=db.update(Constant.TABLE_NAME,cv,Constant._ID+"=3",null);//返回值为int 修改了多少行
if (count>0){
Toast.makeText(this, "成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
}
db.close();
break;
case R.id.shan:
helper= DbManger.getIntance(this);
db=helper.getReadableDatabase();
/**
*delete(String table, String whereClause, String[] whereArgs)
*String table表示插入数据表的名称
* String whereClause 修改条件
* String[] whereArgs 修改条件的占位符
*/
int count2=db.delete(Constant.TABLE_NAME,Constant._ID+"=3",null);
if (count2>0){
Toast.makeText(this, "成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
}
db.close();
break;
查
SQLiteDatabase中提供了一个query()方法用于查询数据。这个方法一共需要传入7个方法
虽然参数很多,但大部分情况都只需要少数参数就可以了;
case R.id.cha:
helper= DbManger.getIntance(this);
db=helper.getReadableDatabase();
Toast.makeText(this, "cha", Toast.LENGTH_SHORT).show();
Cursor cursor=db.query(Constant.TABLE_NAME,null,null,null,null,null,null,null);
if (cursor.moveToFirst()){
do{
//便利cursor
int id=cursor.getInt(cursor.getColumnIndex("_id"));
String name=cursor.getString(cursor.getColumnIndex("name"));
int age=cursor.getInt(cursor.getColumnIndex("age"));
Log.i("1", id+name+age);
}while (cursor.moveToNext());
}
db.close();
break;