1.持久化简介
数据持久化就是指将那些内存中的瞬时数据保存到储存设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失.保存在内存中的数据是处于瞬时状态的,而保存在存储设备中的数据是处于持久状态的,持久化技术提供了一种机制可以让数据在瞬时状态和持久状态直接进行状态.
Android系统主要提供了3种方式实现数据持久化功能:文件储存,SharedPreferences存储,数据库存储.
2.文件存储
文件存储:他不对存储内容进行任何格式化处理,所有数据都是原封不动的保存到文件当中,比较适合存储一些简单的文本数据或二进制数据.
1.将数据存储到文件中
activity_maiin.xml
用来输入文本
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit"
android:hint="Type something here"
/>
MainActivity.class
通过save方法把输入的内容存储到文件中.
public class MainActivity extends AppCompatActivity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit=(EditText) findViewById(R.id.edit);
}
@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 {
out=openFileOutput("data", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(writer!=null){
writer.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
会在/data/data/项目名/files/目录有一个data文件,就是存储的文本内容.
2.从文件中读取数据
public class MainActivity extends AppCompatActivity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit=(EditText) findViewById(R.id.edit);
String inputText=load();
if(!TextUtils.isEmpty(inputText)){
edit.setText(inputText);
edit.setSelection(inputText.length());
Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
}
}
@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 {
out=openFileOutput("data", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
if(writer!=null){
writer.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
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 {
if(reader!=null){
try{
reader.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
return content.toString();
}
}
3.SharedPreferences存储
1.将数据存储到SharedPreferences中
1.Context类中的getSharedPreferences()方法
参数1:指定SharedPreferences文件名称,如果不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/目录
下的
参数2:用于指定操作模式,目前只有MODE_PRIVATE模式,为默认模式,和直接传入0效果是相同的,表示当前的应用程序才可以对这个SharedPreferences文件进行读写.其余模式已被废弃.
2.Activity类中的getPreferences()方法
该方法与Context中的getSharedPreferences()方法相似,不过它只接收一个操作模式参数,因为使用这种方式会自动将当前活动的类名作为SharedPreferences的文件名.
3.PreferenceManager类中的getDefaultSharedPreferences()方法
该方法为静态方法,它接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件.得到了SharedPreferences对象后,就可以开始向SharedPreferences文件存储数据了.
三步实现法:
(1)调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象.
(2)向SharedPreferences.Editor对象中添加数据.
(3)调用apply()方法将添加的数据提交,从而完成数据存储操作.
使用第一种方法
新建项目
activity_main.xml,添加按钮
<Button
android:id="@+id/save_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save data"/>
MainActivity.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button saveData=(Button) findViewById(R.id.save_data);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name","Tom");
editor.putInt("age",28);
editor.putBoolean("married",false);
editor.apply();
}
});
}
}
生成的文件在/data/data/<package name>/shared_prefs/目录
生成一个data.xml文件
2.从SharedPreferences文件读取数据
在activity_main.xml中添加按钮
<Button
android:id="@+id/restore_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Restordata"/>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button saveData=(Button) findViewById(R.id.save_data);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name","Tom");
editor.putInt("age",28);
editor.putBoolean("married",false);
editor.apply();
}
});
Button restoreData=(Button) findViewById(R.id.restore_data);
restoreData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
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);
}
});
}
}
3.实现记住密码功能
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Account:" />
<EditText
android:id="@+id/account"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Password:" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:inputType="textPassword" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/remember_pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="Remember password" />
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Login" />
</LinearLayout>
public class LoginActivity extends BaseActivity {
private SharedPreferences pref;
private SharedPreferences.Editor editor;
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
private CheckBox rememberPass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
pref = PreferenceManager.getDefaultSharedPreferences(this);
accountEdit = (EditText) findViewById(R.id.account);
passwordEdit = (EditText) findViewById(R.id.password);
rememberPass = (CheckBox) findViewById(R.id.remember_pass);
login = (Button) findViewById(R.id.login);
boolean isRemember = pref.getBoolean("remember_password", false);
if (isRemember) {
// 将账号和密码都设置到文本框中
String account = pref.getString("account", "");
String password = pref.getString("password", "");
accountEdit.setText(account);
passwordEdit.setText(password);
rememberPass.setChecked(true);
}
login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
// 如果账号是admin且密码是123456,就认为登录成功
if (account.equals("admin") && password.equals("123456")) {
editor = pref.edit();
if (rememberPass.isChecked()) { // 检查复选框是否被选中
editor.putBoolean("remember_password", true);
editor.putString("account", account);
editor.putString("password", password);
} else {
editor.clear();
}
editor.apply();
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
} else {
Toast.makeText(LoginActivity.this, "account or password is invalid",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
4.SQLite数据库存储
1.创建数据库
SQLiteOpenHelper中有两个实例,getReadableDatabase()
和getWritableDatabase()
.都可以创建或打开一个现有的数据库,并返回一个可对数据库进行读写操作的对象.当数据库不可写入的时候,getReadableDatabase()
方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase()
方法则将出现异常.
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK="create table Book("
+"id integer primary key autoincrement,"+"author text,"+"price real,"+"pages integer,"+"name text)";
private Context mContext;
//Context,数据库名,允许我们在查询数据时返回一个自定义Cursor,数据库版本号
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 sqLiteDatabase, int i, int i1) {
}
}
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database"
android:id="@+id/create_database"
tools:ignore="MissingConstraints" />
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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 view) {
dbHelper.getWritableDatabase();
}
});
}
}
2.升级数据库
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK="create table Book("
+"id integer primary key autoincrement,"+"author text,"+"price real,"+"pages integer,"+"name text)";
public static final String CREATE_CATEGORY="create table Category("+"id integer primary key autoincrement,"+"category_name text,"+"category_code integer)";
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);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//将数据库版本号提升就可让onUpgrade()方法执行.
dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
Button createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dbHelper.getWritableDatabase();
}
});
}
}
3.添加数据
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"
android:id="@+id/add_data"
tools:ignore="MissingConstraints" />
Button addData=(Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
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.put("name","The Lost Symbol");
values.put("author","Dan Brown");
values.put("pages",510);
values.put("price",19.95);
db.insert("Book",null,values);//插入第二条数据
}
});
4.更新数据
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update data"
android:id="@+id/updata_Data"
tools:ignore="MissingConstraints" />
Button updateData=(Button) findViewById(R.id.updata_Data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db=dbHelper.getWritableDatabase();
ContentValues values=new ContentValues();
values.put("price",20.99);
db.update("Book",values,"name=?",new String[]{"The Da VinciCode"});
}
});
5.删除数据
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"
android:id="@+id/delete_data"
tools:ignore="MissingConstraints" />
Button deleteButton=(Button) findViewById(R.id.delete_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db=dbHelper.getWritableDatabase();
db.delete("Book","pages>?",new String[]{"500"});//插入第二条数据
}
});
6.查询数据
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data"
android:id="@+id/query_data"
tools:ignore="MissingConstraints" />
Button queryButton=(Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db=dbHelper.getWritableDatabase();
//查询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();
}
});
7.使用SQL操作数据库
1.添加数据
db.execSQL("insert into Book(name,author,pages,price)values(?,?,?,?)",new String[]{"The Da Vinci Code","Dan Brown","454","16.96"});
2.更新数据
db.execSQL("update Book set price=? where name=?",new String[]{"10.99","The Da Vinci Code"});
3.删除数据
db.execSQL("delete from Book where pages>?",new String[]{"500"});
4.查询数据
db.rawQuery("select *from Book",null);
5.使用LitePal操作数据库
1.LitePal简介
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模型.
2.配置LitePal
在app/build.gradle文件
dependencies{
......
implementation 'org.litepal.android:core:1.4.1'
}
在assets目录下新建litepal.xml文件
<dbname>
用于指定数据库名,<version>
用于指定数据库版本号<list>
用于指定所有的映射模型
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="1"></version>
<list></list>
</litepal>
修改AndroidManifest.xml
<application
android:name="org.litepal.LitePalApplication"
......
/>
3.创建和升级数据库
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;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
修改litepal.xml
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="1"></version>
<list>
<mapping class="com.example.litepaltest.Book"></mapping>
</list>
</litepal>
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LitePal.getDatabase();
}
});
}
}
添加字段
public class Book{
...
private String press;
public String getPress(){
return press;
}
public void setPress(String press){
this.press=press;
}
}
添加新表
public class Category {
private int id;
private String categoryName;
private int categoryCode;
public void setId(int id) {
this.id = id;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public void setCategoryCode(int categoryCode) {
this.categoryCode = categoryCode;
}
}
litepal.xml
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="BookStore"></dbname>
<version value="2"></version>
<list>
<mapping class="com.example.litepaltest.Book"></mapping>
<mapping class="com.example.litepaltest.Category"></mapping>
</list>
</litepal>
4.使用LitePal添加数据
public class Book extends DataSupport{
...
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createDatabase=(Button) findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LitePal.getDatabase();
}
});
Button addData=(Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
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();
}
});
}
}
5.使用LitePal更新数据
Button updateData=(Button) findViewById(R.id.updata_Data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Book book=new Book();
book.setPrice(14.95);
book.setPress("Anchor");
book.updateAll("name=?and author=?","The Lost Symbol","Dan Brown");
});
setToDefault()
方法可以让属性变为默认值.
Book book=new Book();
book.setToDefault("pages");
book.updateAll();
6.使用LitePal删除数据
Button deleteButton=(Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DataSupport.deleteAll(Book.class,"price<?","15");
}
});
7.使用LitePal查询数据
Button queryButton=(Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<Book> books=DataSupport.findAll(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.getPrice());
}
}
});
查询表中第一条数据
Book firstBook=DataSupport.findFirst(Book.class);
查询表中最后的数据
Book lastBook=DataSupport.findLast(Book.class);
select()方法用于指定查询那几列的数据
List<Book> books=DataSupport.select("name","author").find(Book.class);
where()方法用于指定查询的约束条件
List<Book> books=DataSupport.where("pages>?","400").find(Book.class);
order()方法指定结果的排序方式
List<Book> books=DataSupport.order("price desc").find(Book.class);//desc降序排序,asc升序排序
limit()方法用于指定查询结果的数量.
List<Book> books=DataSupport.limit(3).find(Book.class);
offset()方法用于指定查询结果的偏移量.
List<Book> books=DataSupport.limit(3).offset(1).find(Book.class);