数据持久化技能就是将内存中瞬时数据保存到存储设备中,保证关机大概重启之后不会数据丢失。
6.1持久化技能简介
Android中紧张提供了三种方式用于简单的实现数据持久化功能,即文件存储、SharedPreference存储以及数据库存储。除此之外,另有其他方式,比如说存在SD卡中。文件存储、SharedPreference存储以及数据库存储这三种比存在SD卡中简单,而且更安全。
6.2 文件存储
文件存储不对数据举行任何格式化的处理,得当存储一些简单的文本数据或二进制数据。如果想要存储复杂的数据,就要自定义一套本身的格式规范,如许以后方便从文件中重新解析出来。
将数据存储到文件中
Context类提供了一个openFileOutput()方法,可将数据存到文件中。
这个方法吸收两个参数:
- 第一个参数:文件名。(不可以包含路径,都默认存储到/data/data/<package name/files/)
- 第二个参数:文件的使用模式。有两种。
- MODE_PRIVATE:默认使用模式,指定同名文件会覆盖源文件内容。
- MODE_APPEND:如果文件存在,则往文件末了追加内容。不存在同名文件则创建新文件。
openFileOutput()返回一个FileOutputStream对象,得到该对象可以使用Java流的方式将数据写入到文件中了。
- public void save(){
- String data="Data to save";
- FileOutputStream out=null;
- BufferedWriter writer=null;
- try{
- out=openFileOutput("data", Context.MODE_PRIVATE);
- writer=new BufferedWriter(new OutputStreamWriter(out));
- }
- catch (IOException e){
- e.printStackTrace();
- }
- finally {
- try {
- if(writer!=null){
- writer.close();
- }
-
- } catch (IOException e){
- e.printStackTrace();
- }
- }
- }
复制代码 从文件中读取数据
- public class MainActivity extends AppCompatActivity {
- private EditText edit;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- EdgeToEdge.enable(this);
- setContentView(R.layout.activity_main);
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
- Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
- return insets;
- });
- 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();
- }
- }
- public void save(String inputText){
- String data="Data to save";
- 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 void onDestroy(){
- super.onDestroy();
- String inputText=edit.getText().toString();
- save(inputText);
- }
- public String load(){
- FileInputStream in=null;
- BufferedReader read=null;
- StringBuilder content=new StringBuilder();
- try{
- in=openFileInput("data");
- read=new BufferedReader(new InputStreamReader(in));
- String line="";
- while((line =read.readLine())!=null){
- content.append(line);
- }
- }catch (IOException e){
- e.printStackTrace();
- }
- finally {
- try {
- if(read!=null){
- read.close();
- }
- } catch (IOException e){
- e.printStackTrace();
- }
- }
- }
- }
复制代码 6.3 SharedPreferences存储
不同于文件的存储方式。这个是使用键值对的方式来存储数据的。保存一条数据的时候,需要给这条数据提供一个对应的键。这个存储方式支持多种不同的数据范例。如果存储的数据范例是整型,那么读取出来的数据也是整形。如果存储的数据是字符串,那么读取出来的数据也是一个字符串。
6.3.1 将数据存储到是SharedPreferences中
如果要想使用SharedPreferences,以是先要获取到SharedPreferences对象。安卓一共的三种方法用来得到是SharedPreferences对象。
- Context类中的getSharedPreferences()方法。
此方法吸收两个参数,第一个参数用于指定这个文件的名称,如果指定的文件不存在,则会创建一个新的,SharedPreferences文件都是存放在/data/data/<package name /<shared_prefs目录下。
第二个参数用于指定使用模式,目前只有MODE_PRIVATE一种模式可选,它是默认的使用模式。和直接传入0的效果是相同的,只有当前的应用步伐才可以对这个SharedPreferences文件举行读写。其他几种使用模式均已被废弃。
- Activity类中的getPreferences()方法。
这个方法和第一个Context类中的getSharedPreferences()方法很相似,不过这个方法只接受一个参数。使用这个方法会自动将当前活动的类名作为SharedPreferences文件名。
- PreferenceManager类的getDefaultSharedPreferences()方法
是一个静态的方法,它接自动使用当前应用步伐的包名作为前缀来命名这个SharedPreferences文件。得到了这个SharedPreferences对象之后就开始向这个文件中存储数据了。紧张分为以下三个步骤实现:
第一步,要用这个SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。
第二步,向这个SharedPreferences.Editor对象中添加数据,比如添加一个布尔型就用这个putBoolean()方法。添加一个字符串,则使用putString()方法,以此类推。
第三步,用apply()方法将添加的数据提交,从而完成数据存储。
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- EdgeToEdge.enable(this);
- setContentView(R.layout.activity_main);
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
- Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
- return insets;
-
-
- });
- Button saveData=(Button) findViewById(R.id.save_data);
- saveData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
- editor.putString("name","Tom");
- editor.putBoolean("married",false);
- editor.putInt("age",28);
- editor.apply();
- }
- });
- }
- }
复制代码 6.3.2 从SharedPreferences中读取数据
每一种get方法都对应了一种put的方法。
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- EdgeToEdge.enable(this);
- setContentView(R.layout.activity_main);
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
- Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
- return insets;
- });
- Button saveData=(Button) findViewById(R.id.save_data);
- saveData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
- editor.putString("name","Tom");
- editor.putBoolean("married",false);
- editor.putInt("age",28);
- editor.apply();
- }
- });
- Button restoreData=(Button) findViewById(R.id.restore_data);
- restoreData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SharedPreferences pref=getSharedPreferences("data",MODE_PRIVATE);
- String name=pref.getString("name","");
- int age=pref.getInt("age",0);
- boolean married=pref.getBoolean("married",false);
-
- }
- });
- }
- }
复制代码 6.3.3 实现记住暗码功能
activity_login.xmll
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <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:textSize="18sp"
- android:text="Remeber password"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- <Button
- android:id="@+id/login"
- android:layout_width="match_parent"
- android:layout_height="60dp"
- android:text="Login"/>
- </LinearLayout>
复制代码 LoginActivity.java
- package com.example.broadcastbestpractice;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.os.Bundle;
- 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 java.util.prefs.PreferenceChangeEvent;
- public class LoginActivity extends BaseActivity{
- private EditText accountEdit;
- private EditText passwordEdit;
- private Button login;
- private SharedPreferences pref;
- private SharedPreferences.Editor editor;
- private CheckBox rememberPass;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_login);
-
- pref = PreferenceManager.getDefaultSharedPreferences(this);
- rememberPass=(CheckBox)findViewById(R.id.remember_pass);
- boolean isRemeber=pref.getBoolean("remember_password",false);
- if(isRemeber){
- //将账号和密码都设置到文本框
- String account=pref.getString("account","");
- String password=pref.getString("password","");
- accountEdit.setText(account);
- passwordEdit.setText(password);
- rememberPass.setChecked(true);
- }
- accountEdit=(EditText) findViewById(R.id.account);
- passwordEdit=(EditText) findViewById(R.id.password);
- login=(Button) findViewById(R.id.login);
- login.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String account=accountEdit.getText().toString();
- String password=passwordEdit.getText().toString();
- if(account.equals("admin")&&password.equals("123")){
- editor=pref.edit();
- //如果复选框被选中
- if(rememberPass.isChecked()){
- editor.putBoolean("remember_pass",false);
- 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 id invalid",Toast.LENGTH_SHORT).show();
- }
- }
- });
- }
- }
复制代码 6.4 SQLite数据库存储
这是一款轻量级的关系型数据库,它的运算速率非常快,但资源很少,通常只需要几百kb的内存就足够了,因此特别得当在移动设备上使用。SQLite不但支持标准的SQL语,还依照数据库的acid事务。
6.4.1 创建数据库
安卓为了让我们可以或许更加方便的管理数据库,专门提供了一个SQLiteOpenHelper主类。借助这个类就可以非常简单的对数据库举行创建和升级。
- SQLiteOpenHelper这一个抽象类,如果要使用这个类的话,就需要创建一个本身的资助类去继续它。
- SQLiteOpenHelper有两个抽象方法。一个是onCreate(),一个是onupgrade()。需在本身的资助类内里重写这两个方法。分别在这两个方法中去实现创造和升级数据库的逻辑。
- SQLiteOpenHelper另有两个非常紧张的实例方法。一个是getReadableDatabase(),另一个是getWritableDatabase()。两个方法都可以创建大概打开一个现有的数据库,如果数据库已经存在则打开,否则创建一个新的数据库。并返回一个可对数据库举行读写使用的对象。不同的是,当数据库不可写入的时候,比如磁盘空间已满。getReadableDatabase()方法返回的对象将以只读的方式去带数据。getWritableDatabase()方法则将出现异常。
- 有两个构造方法可以重写,一般使用参数少一点的谁人构造方法即可。是构造函数方法中吸收四个参数,第一个参数是context,必须有这个才气对数据库举行使用。第二个参数是数据库名,创建数据库时使用的就是这里指定的名称。第三个参数答应我们在查询数据的时候返回一个自定义的Cursor游标,一般都是传入nulll。第四个参数,表示当前数据库的版本号,可用于对数据库举行升级使用。构建出的实例之后再调用它的getReadableDatabase()大概getWritableDatabase()方法就可以或许创建数据库。数据库的文件存放在/data/data/<package name/databases/目录下,此时重写的onCreate的方法也会执行。以是通常会在这里行止理一些创建表的逻辑。
- public class MainActivity extends AppCompatActivity {
- private MyDatabaseHelper dbHelper;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- EdgeToEdge.enable(this);
- setContentView(R.layout.activity_main);
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
- Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
- return insets;
- });
-
- dbHelper=new MyDatabaseHelper(this,"BookStroe.db",null,1);
- Button createDatabase=(Button) findViewById(R.id.creat_database);
- createDatabase.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dbHelper.getWritableDatabase();
- }
- });
- }
- }
复制代码- public class MyDatabaseHelper extends SQLiteOpenHelper {
- public final String CREATE_BOOK ="create table book ("
- + "id integer primary key autoincrement, "
- + "author text,"
- + "price real,"
- +"pages 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);
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- }
- }
复制代码 6.4.2 升级数据库
再加一个数据库表,记载图书的分类。
- public class MyDatabaseHelper extends SQLiteOpenHelper {
- public final String CREATE_BOOK ="create table book ("
- +"id integer primary key autoincrement, "
- +"author text,"
- +"price real,"
- +"pages integer,"
- +"name text)" ;
- public 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 成功",Toast.LENGTH_SHORT).show();
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- }
- }
复制代码 看上去挺对的,现在运行一下步伐,点击Create database按钮,没有弹出"Create 成功"的提示。
没有创建成功的缘故原由是因为之前的bookstore数据库已经存在了,不管怎样点Create database按钮,这个oncreate方法中都不会再次执行,因此新添加的表就无法得到。
解决方法有两种。一种是卸载步伐重新运行。另一种方法是在升级功能函数内里加下面几行代码。
- @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);
- }
复制代码 如何让这个onUpgrage的方法可以或许执行?SQLiteOpenHelper的构造方法吸收四个参数,最后一个参数是版本号,版本号默认传入是1,只要传入一个比1大的数就可以让onUpgrade的方法执行。
。。。
dbHelper=new MyDatabaseHelper(this,“BookStroe.db”,null,2);
Button createDatabase=(Button) findViewById(R.id.creat_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
。。。
6.4.3 添加数据
- Button addData=(Button) findViewById(R.id.addData);
- addData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SQLiteDatabase db=dbHelper.getWritableDatabase();
- ContentValues values=new ContentValues();
- values.put("name","The Da vinci Code");
- values.put("pages",454);
- db.insert("Book",null,values);
-
- values.clear();
- values.put("name","the lost Symbol");
- values.put("pages",349);
- db.insert("Book",null,values);
- }
- });
复制代码 6.4.4 更新数据
找到书名为The Davinci Code的一组数据,将这本书的价格改为17.52
- Button updateData=(Button) findViewById(R.id.updateData);
- addData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SQLiteDatabase db=dbHelper.getWritableDatabase();
- ContentValues values=new ContentValues();
- values.put("price",17.52);
- db.update("Book",values,"name=?",new String[]{"The Davinci Code"});
- }
- });
复制代码 6.4.5 删除数据
删除页数超过500页的书
- Button deleteData=(Button) findViewById(R.id.deleteData);
- deleteData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SQLiteDatabase db=dbHelper.getWritableDatabase();
- ContentValues values=new ContentValues();
- db.delete("Book","pages>?",new String[]{"500"});
- }
- });
复制代码 6.4.6 查询数据
- Button queryData=(Button) findViewById(R.id.queryData);
- queryData.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- SQLiteDatabase db=dbHelper.getWritableDatabase();
- Cursor cursor=db.query("Book",null,null,null,null,null,null);
- if(cursor.moveToFirst()){
- do{
- @SuppressLint("Range") String name=cursor.getString(cursor.getColumnIndex("name"));
- @SuppressLint("Range") int pages=cursor.getInt(cursor.getColumnIndex("pages"));
- }while(cursor.moveToNext());
- }
- cursor.close();
- }
- });
复制代码 6.4.7 使用SQL使用数据库
直接使用SQL来完成增删改查。
添加数据
db.execSQL(“insert into Book (name,author,pages,price) values(?,?,?,?)”,new String[]{“The Da Vinci Code”,"Dan ",“454”,“16.35”} );
查询数据
db.rawQuery(“select * from Book”,null);
6.5 使用LitePal使用数据库
6.5.1 LitePal简介
是一个开源的Android数据库框架。接纳了对象关系映射(ORM)的模式,并将我们平时开发最常用的一些数据库功能举行了封装。不消编写SQL就完成增删改查。
6.5.2 配置LitePal
怎样才气在项目中使用开源库?已往的方式比力复杂,下载开源库的jar包大概源码,然后再集成到项目中。现在简单多了,大多数的开源项目都会将版本提交到jcenter上,需要在app/build.gradle文件中声明该开源库的引用就可以了。
后续更新…
6.5.3 创建和升级数据库
6.5.4 增加
6.5.5 更新
6.5.6 删除
6.5.6 查询
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |