持久化技术
数据持久化就是指将内存中短暂存储的瞬时数据保存到存储设备中,保证在手机或电脑关机情况下,数据不会丢失。
三种常见的持久化技术
文件存储
不对存储内容进行任何处理,所有数据被原封不动保存到文件中去,适用于保存短小的文本文件或是二进制数据。
数据保存到文件中去
package cn.ywrby.filepersistencetext;
import android.content.Context;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import java.io.*;
public class MainActivity extends AppCompatActivity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit=findViewById(R.id.et_1);
}
//定义销毁活动的方法,保存此时输入框中的数据
@Override
protected void onDestroy() {
super.onDestroy();
String inputText=edit.getText().toString(); //获取输入框数据
save(inputText); //保存到相应文件
}
//定义存储方法
public void save(String inputText){
FileOutputStream out=null;
BufferedWriter writer=null;
try {
/*
Context类提供openFileOutput方法用于将数据存储到指定文件夹
参数一表示文件名(不包含文件路径,因为所有文件的默认保存路径都是/data/data/<package name>/files/)
参数二表示文件操作模式,有两种可选:MODE_PRIVATE默认操作模式,表示当文件同名时,新文件会覆盖旧文件内容
MODE_APPEND当文件存在时,会在文件中追加新写入内容,文件不存在则新建
*/
out=openFileOutput("data", Context.MODE_PRIVATE);
//将FileOutputStream包装成OutputStreamWriter然后再包装成更高级的BufferedWriter
writer=new BufferedWriter(new OutputStreamWriter(out));
try {
writer.write(inputText); //写入数据
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭文件
if(writer!=null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
从文件中读取数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit=findViewById(R.id.et_1);
String inputText=load();
if(!TextUtils.isEmpty(inputText)){
edit.setText(inputText);
edit.setSelection(inputText.length());
Toast.makeText(this,"Restoring succeed!",Toast.LENGTH_SHORT).show();
}
}
//定义读取文件方法
public String load(){
FileInputStream in=null;
BufferedReader reader=null;
StringBuilder content=new StringBuilder(); //定义可变字符串,用于读取文件内容
try {
in=openFileInput("data");
reader=new BufferedReader(new InputStreamReader(in));
String line="";
//逐行读取
while((line=reader.readLine())!=null){
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return content.toString();
}
package cn.ywrby.sharedpreferencetext;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private EditText et_account;
private EditText et_password;
private CheckBox checkBox;
private Button login;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_account=findViewById(R.id.et_acount);
et_password=findViewById(R.id.et_password);
checkBox=findViewById(R.id.cb_save);
login=findViewById(R.id.bt_login);
pref= PreferenceManager.getDefaultSharedPreferences(this);
boolean isRemember=pref.getBoolean("remember_password",false);
if(isRemember){
String account=pref.getString("account","");
String password=pref.getString("password","");
et_account.setText(account);
et_password.setText(password);
checkBox.setChecked(true);
}
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String account=et_account.getText().toString();
String password=et_password.getText().toString();
if(account.equals("admin") && password.equals(("123456"))){
editor=pref.edit();
if(checkBox.isChecked()){
editor.putBoolean("remember_password",true);
editor.putString("account",account);
editor.putString("password",password);
}else {
editor.clear();
}
editor.apply();
Toast.makeText(MainActivity.this,"Successful login",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"account or password is invalid",Toast.LENGTH_SHORT).show();
}
}
});
}
}
SQLite数据库存储
Android系统内置的数据库,一种轻量级关系型数据库,支持标准SQL语法,遵循数据库的ACID事务
SQLiteOpenHelper类
用于控制数据库进行创建和升级的帮助类。一个抽象类
package cn.ywrby.databasetext;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import androidx.annotation.Nullable;
public class MyDatabaseHelper extends SQLiteOpenHelper {
/*
SQLiteOpenHelper帮助类是安卓提供的用于对数据库进行创建和升级的类
SQLiteOpenHelper是一个抽象类,所以需要我们继承并重写其中的两个抽象方法
两个抽象方法分别是onCreate()用于创建数据库
onUpgrade()用于对数据库进行升级
SQLiteOpenHelper类害提供了两个重要的实例方法:getReadableDatabase(),getWritableDatabase()
这两个方法都可以创建或打开一个现有的数据库,并返回一个可对数据库进行操作的对象
*/
private Context mContext;
//将建表语句定义为一个字符串常量
/*
sqlite支持标准的sql语句,并且对数据类型做了精简
integer表示整型
real表示浮点型
text表示文本
blob表示二进制类型
*/
public static final String CREATE_BOOK="create table book ("
+"id integer primary key autoincrement," //primary key指定id为逐渐,并用autoincrement修饰表示id是自增长的
+"author text,"
+"price real,"
+"pages integer,"
+"name text)";
public static final String CREATE_CATAEGORY="create table category ("
+"id integer primary key autoincrement," //primary key指定id为逐渐,并用autoincrement修饰表示id是自增长的
+"category_name text,"
+"catagory_code integer)";
/*
第二个参数表示数据库的名称,第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入null,第四个参数表示当前数据库的版本号
*/
public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext=context;
}
/*
创建方法,第一次被调用时会检测是否有“BookStore.db”这个数据库
不存在就创建,存在就不再执行onCreate方法,即便两次的方法内容不一样
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK); //执行建表语句
db.execSQL(CREATE_CATAEGORY);
Toast.makeText(mContext,"CREATE TABLE SUCCEEDED",Toast.LENGTH_SHORT).show();
}
/*
升级方法,通过提高版本号来控制执行,用于对数据库中内容进行升级
*/
@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);
}
}
主程序
package cn.ywrby.databasetext;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
//创建帮助类
private MyDatabaseHelper helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//传入Context,数据库名,返回cursor设为null,版本号
//版本号大于之前时会调用升级方法
helper=new MyDatabaseHelper(this,"BookStore.db",null,2);
Button bt_create=findViewById(R.id.bt_create);
bt_create.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
helper.getWritableDatabase(); //调用帮助类的getWritableDatabase方法
}
});
}
}
adb shell的使用
1. 进入abd工具的设备控制台
adb shell
2. 获取root用户权限
su
3. 查看数据库
sqlite3 数据库名
4. 查看数据库中所有表格
.table
5. 查看所有建表语句
.schema
添加数据
//插入数据
Button bt_add=findViewById(R.id.bt_add);
bt_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过getReadableDatabase获得可对数据库进行操作的SQLiteDatabase对象
SQLiteDatabase db=helper.getReadableDatabase();
//ContentValues提供了一系列put方法用于向ContentValues中传入数据
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);
//向数据库中插入数据,第一个参数是表名,第二个参数是用于在未指定添加数据的情况下为某些可为空的列自动赋值为空
//第三个参数就是ContentValues对象,其内包含已经插入的数据
db.insert("book",null,values);
values.clear();
values.put("name","The Lost Symbol");
values.put("author","Dan Brown");
values.put("pages",510);
values.put("price",19.95);
db.insert("book",null,values);
Toast.makeText(MainActivity.this,"add data succeeded!",Toast.LENGTH_SHORT).show();
}
});
更新数据
//升级数据
Button bt_update=findViewById(R.id.bt_update);
bt_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=helper.getReadableDatabase();
ContentValues values=new ContentValues();
values.put("price",10.99);
db.update("book",values,"name=?",new String[]{"The Da Vinci Code"});
//第一个参数是表名,第二个是ContentValues对象,里边包含了修改过的值
//第三个参数指明修改的具体行,这里的“?”表示占位符,第四个参数用来指明占位符处填写的内容
}
});
删除数据
//删除数据
Button bt_delete=findViewById(R.id.bt_delete);
bt_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=helper.getReadableDatabase();
db.delete("book","pages>?",new String[]{"500"});
}
});
查询数据
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 | 指定查询结果的排序方式 |
//查询数据
Button bt_query=findViewById(R.id.bt_query);
bt_query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=helper.getReadableDatabase();
//查询表中所有数据
Cursor cursor=db.query("book",null,null,null,null,null,null);
if(cursor.moveToFirst()){
do{
//遍历cursor对象,取出数据并打印
String name=cursor.getString(cursor.getColumnIndex("name"));
int pages=cursor.getInt(cursor.getColumnIndex("pages"));
Log.d("QueryData","book name is "+name);
Log.d("QueryData", "book pages is"+pages );
}while(cursor.moveToNext());
}
cursor.close();
}
});