持久化技术

一、持久化技术

1.数据持久化:

将内存中的瞬时数据保存到存储设备中。

2.持久化技术的三种方式:

文件存储、SharedPreferences存储、数据库存储

二、SharedPreferences存储

使用键值对的方式存储数据。读取数据时通过键把相应的值读出来
存储路径:存储位置在/data/data/<包名>/shared_prefs目录下

1.将数据存储到SharedPreferences中

要使用SharedPreferences来存储数据,首先要获得SharedPreferences对象。
SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现

获取SharedPreferences对象的三种方法:

1.Context类中的getSharedPreferences()方法
getSharedPreferences(String name, int mode):

  • 第一个参数:指定SharedPerferences文件的名称,若指定的文件不存在则会创建一个。
  • 第二个参数:指定操作模式。只有MODE_PRIVATE一种模式。

2.Activity类中的getPreferences()方法
getPreferences(int mode):参数为操作模式

使用该方法会自动将当前活动的类名作为SharedPreferences的文件名

3.PreferenceManager类中的getDefaultSharedPreferences()方法
getDefaultSharedPreferences(Context context):参数为context

存储数据步骤:
(1)SharedPreferences对象调用edit()方法得到SharedPreferences.Editor对象
(2)调用SharedPreferences.Editor对象的putInt()、putString()、putBoolean()等方法向SharedPreferences.Editor对象中添加数据
(3)调用apply()方法将添加的数据提交

activity_main.xml中设置一个按钮布局即可,这里省略

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveData = findViewById(R.id.button);
        saveData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取SharedPreferences.Editor对象
                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
                //添加数据
                editor.putString("name","Tom");
                editor.putInt("age",25);
                editor.putBoolean("married",false);
                //提交
                editor.apply();
            }
        });
    }

方法解析:
getSharedPreferences(String name, int mode):指定存储数据的文件名并得到SharedPreferences对象
edit():获取SharedPreferences.Editor对象
putXXX(String var1,XXX var2):添加不同类型的数据。参数一是key值,参数二是value值
apply():提交数据

查看生成的文件:View-ToolWindows-Device File Explorer,进入
/data/data/com.example.myapplication.sharedpreferencestest/shared_prefs/目录下可查看到生成的data.xml文件

2.从sharedPreferences中读取数据

(1)创建SharedPreferences对象
(2)调用SharedPreferences对象的getString()等方法取出数据

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveData = findViewById(R.id.button);
        saveData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取SharedPreferences对象
                SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
                //获取SharedPreferences中存储的数据
                String name = pref.getString("name", "");
                int age = pref.getInt("age",0);
                boolean married = pref.getBoolean("married", false);
                //通过Log将获取的数据打印出来
                Log.d("MainActivity","name is"+name);
                Log.d("MainActivity","age is"+age);
                Log.d("MainActivity","married is"+married);
            }
        });
    }

方法解析:
getInt(String var1,int var2):取出int类型的数据。参数一为key值,参数二为默认值。即如果没有找到相应的值,则传入默认值

向SharedPreferences中存数据是SharedPreferences.Editor对象调用putInt()等方法
从SharedPreferences中取数据是SharedPreferences对象调用getInt()等方法

三、SQLite数据库存储

1.SQLite基本知识

SQLite是Android内置的轻量型数据库
数据库文件会存放在:/data/data//databases/数据库名
SQLite的数据类型
integer:整型,real:浮点型,text:文本类型,blob:二进制类型
SQLiteOpenHelper:对数据库进行创建和升级的抽象类。
(1)抽象方法:

  • onCreate():创建数据库

  • onUpgrade():升级数据库

(2)构造方法:
SQLiteOpenHelper():

  • 第一个参数:Context
  • 第二个参数:数据库名
  • 第三个参数:允许查询数据时返回一个自定义的Cursor,一般传入null
  • 第四个参数:当前数据库的版本号,可用于对数据库升级

2.创建数据库

  • getReadableDatabase():创建或打开一个现有的数据库(数据库不存在则创建,存在直接打开)。当数据库不可写入时,返回对象以只读方式打开数据库。
  • getWritableDatabase():创建或打开一个现有的数据库(数据库不存在则创建,存在直接打开)。当数据库不可写入时,该方法报异常。
  • execSQL(String sql):执行sql语句

(1)创建一个自定义类继承SQLiteOpenHelper抽象类,重写onCreate()和onUpgrade()
(2)创建SQL语句,并将sql语句定义成字符串常量
(3)在onCreate()方法中调用execSQL()方法执行sql语句
(4)创建自定义类的对象,指定数据库名和数据库版本号
(5)执行getWritableDatabase()方法创建数据库

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //创建SQL语句
    public static final String CREATE_BOOK = "create table Book("
            +"id integer primary key autoincreament,"
            +"author text,"
            +"price real,"
            +"name text)";
    private Context context;
    public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        //执行sql语句
        db.execSQL(CREATE_BOOK);
        Toast.makeText(context,"Created successed",Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }
}

省略activity_main.xml的代码

public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建MyDatabaseHelper对象。指定数据库名为Book.db
        dbHelper = new MyDatabaseHelper(this,"Book.db",null,1);
        Button createDatabase = findViewById(R.id.button);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //创建数据库
                dbHelper.getWritableDatabase();
            }
        });
    }

public SQLiteOpenHelper(Context context, String name,CursorFactory factory, int version)

  • 第一个参数:上下文
  • 第二个参数:数据库名
  • 第四个参数:数据库版本号

3.升级数据库

想在数据库中再添加一个表
(1)在onCreate()方法里执行新的sql语句,并在onUpgrade()方法里删除已存在的表并调用onCreate()方法。
(2)将数据库版本指定为2

public class MyDatabaseHelper extends SQLiteOpenHelper {
    //创建SQL语句
    public static final String CREATE_BOOK = "create table Book("
            +"id integer primary key autoincreament,"
            +"author text,"
            +"price real,"
            +"name text)";
    public static final String CREATE_CATEGORY = "create table Category("
            +"id integer primary key autoincreament,"
            +"category_name text)";
    private Context context;

    public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //执行sql语句建表
        db.execSQL(CREATE_BOOK);
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(context,"Created successed",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);
    }
}

修改MainActivity,将数据库版本改为2:

 //指定数据库版本为2,表示对数据库进行了升级
 dbHelper = new MyDatabaseHelper(this,"Book.db",null,2);

4、添加数据

SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法不仅可以用于创建和升级数据库,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了
(1)创建SQLiteDatabase对象
(2)创建ContentValues对象
(3)ContentValues对象调用put()方法组装数据到ContentValues中
(4)SQLiteDatabase对象调用insert()方法将ContentValues中的数据插入到表中

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,"Book.db",null,2);
        Button addData = findViewById(R.id.add);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取SQLiteDatabase对象
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                //创建ContentValues对象用于存储要添加到表中的数据
                ContentValues values = new ContentValues();
                //组装第一条数据到ContentValues对象
                values.put("name","Android");
                values.put("author","Tom");
                values.put("price",32.00);
                //向数据库的Book表中插入第一条数据
                db.insert("Book",null,values);
                //清空ContentValues对象里存的值,以便存新数据
                values.clear();
                //组装第二条数据
                values.put("name","Java");
                values.put("author","Jack");
                values.put("price",42.00);
                //向数据库的Book表中插入第二条数据
                db.insert("Book",null,values)}
        });
    }

方法详解:
Contentvalues:是一种存储基本类型的数据的类,类似于HashMap<String,基本数据类型>这种形式。通过put()方法以键值对的方式存储数据。
insert(String table, String nullColumnHack, ContentValues values) :向表中添加数据

  • 第一个参数:表名
  • 第二个参数:在未指定添加数据的情况下给某些可为空的列自动赋值null
  • 第三个参数:ContentValues对象

put(String key, String value):向ContentValues对象中添加数据。将表中每个列名及相对应待添加的数据传入即可。
clear():清空ContentValues中的数据

5、更新数据

(1)将更新数据组装到ContentValues对象里
(2)SQLiteDatabase调用update()方法
修改MainActivity中OnClick()中的代码为:

			@Override
            public void onClick(View view) {
                //获取SQLiteDatabase对象
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                //将修改的数据组装到ContentValues对象中
                values.put("price",30.00);
                //修改Book表中name为Android的行
                db.update("Book",values,"name=?",new String[]{"Android"});
            }	

方法详解:
update(String table, ContentValues values, String whereClause, String[] whereArgs):更新表中的数据

  • 第一个参数:表名
  • 第二个参数:ContentValues对象
  • 第三个参数和第四个参数:用于约束更新某一行或某几行的数据。不指定默认更新所有行

6、删除数据

            @Override
            public void onClick(View view) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                //删除Book表中price>30的书
                db.delete("Book","price>?",new String[]{"30.00"});
            }

方法详解:
delete(String table, String whereClause, String[] whereArgs):删除表中的数据
第二、三个参数:用于约束删除某一行或某几行的数据。不指定默认更新所有行

7、查询数据

(1)创建SQLiteDatabase对象
(2)SQLiteDatabase对象调用query()方法查询到数据并返回Cursor对象
(3)遍历Cursor对象,

query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) :查询表中的数据。返回值为Cursor对象。

  • 第一个参数:指定查询的表名
  • 第二个参数:指定查询的列名
  • 第三个参数:指定where的约束条件
  • 第四个参数:where占位符具体值
  • 第五个参数:指定需要group by的列
  • 第六个参数:对group by后的结果进一步约束
  • 第七个参数:指定查询结果的排序方式
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,"Book.db",null,2);
        Button queryData = findViewById(R.id.query);
        queryData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                //查询表中的所有数据
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                //将数据指针移到第一行
                if(cursor.moveToFirst()){
                    do{
                        //遍历Cursor对象,取出Cursor对象中的数据
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        /*cursor.getColumnIndex("author"):得到第一行author列的下标索引值,
                     
                        */
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        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 price is"+"price");
                    }while(cursor.moveToNext());
                }
                //关闭游标
                cursor.close();
            }

原理:

先将查询出来的数据一行行存储到Cursor中,将光标定位到第一行。再调用Cursor的getColumnIndex()方法得到第一行每列的下标索引。调用Cursor的getString()、getDouble()、getInt()等方法取出第一行指定下标对应的值。将光标依次后移,取出每行的值。

方法详解:
Cursor:Cursor是数据库中每行的值。query()方法查询到的所有数据都会放到Cursor对象里。

Cursor的方法:

  • getColumnIndex(String var1):获取到某一列在表中对应的位置索引
  • getCount():返回Cursor 中的行数
  • moveToFirst():移动光标到第一行,返回值为boolean
  • moveToLast():移动光标到最后一行
  • moveToNext():移动光标到下一行
  • moveToPosition(int position):移动光标到一个绝对的位置
  • getString(int columnIndex)、getInt(int columnIndex)、getDouble(int columnIndex):返回当前行指定列的值

8.使用SQL语句操作数据库

添加数据:
db.execSQL(“insert into Book(name,author,price) values (?,?,?,?)”,new String[]{“Android”,“Jack”,“27.00”});
更新数据:
db.execSQL(“update Book set price = ? where name = ?”,new String[]{“25.00”,“Android”});
删除数据:
db.execSQL(“delete from Book where price >?”,new String[]{“30”});
查询数据:
db.rawQuery(“select * from Book”,null);

除了查询数据使用SQLiteDatabase的rawQuery()方法,其他都使用execSQL()

四、LitePal操作数据库

1.LitePal简介

开源的Android数据库框架,采用对象关系映射的模式。不用编写一行SQL语句就能完成建表和增删改查操作。

2.配置LitePal

(1)在app/build.gradle文件的dependencies闭包中添加:
implementation 'org.litepal.android:java:3.0.0’
(2)配置litePal.xml文件
在main目录下创建assets目录,在该目录下新建litePal.xml文件。文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value="BookStore"></dbname>
    <version value="1"></version>
    <list>
        <mapping class="com.example.myapplication.Book"></mapping>
    </list>
</litepal>

<dbname>:用于指定数据库名
<version>:用于指定数据库版本号
<list>:用于指定所有的映射模型
<mapping>:声明要配置的映射模型类
(3)AndroidManifest.xml标签中配置litepal
在application标签中加 android:name="org.litepal.LitePalApplication"

   <application
        android:name="org.litepal.LitePalApplication"
        android:allowBackup="true"
        ...
    </application>

3.创建和升级数据库

创建数据库
(1)创建实体类,该类对应数据库中的表。并将该类添加到映射模型列表中

public class Book {
	private int id;
    private String name;
    private String author;
    private Double price;
    //getter、setter方法省略
}

该Book类对应数据库中的Book表。记得要将该类添加到映射模型列表中(list标签中)

(2)Connector调用getDatabase()方法创建数据库

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) {
                //创建数据库
                Connector.getDatabase();
            }
        });
    }

方法详解:
getDatabase():创建数据库

升级数据库
修改要改的内容,将数据库版本号加1
向Book表中添加一个press列,并在BookStore数据库添加新表Category

public class Book {
    private String press;
    //省略getter、setter方法
}
public class Category {
    private int id;
    private String categoryName;
    private int categoryCode;
    //getter、setter方法省略
}

在litepal.xml中将版本号加1,并在list中添加新的模型类

<litepal>
    <dbname value="BookStore"></dbname>
    <version value="2"></version>
    <list>
        <mapping class="com.example.myapplication.Book"></mapping>
        <mapping class="com.example.myapplication.Category"></mapping>
    </list>
</litepal>

4.添加数据

LitePal进行增删改查操作必须模型类必须继承LitePalSupport类。(DataSupport类已被弃用)

public class Book extends LitePalSupport{
...
}
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       ...
        Button addData = (Button)findViewById(R.id.add_data);
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Book book = new Book();
                //调用set()对Book中的值进行设置
                book.setName("Android");
                book.setAuthor("Jack");
                book.setPrice(30.00);
                book.setPress("Unknow");
                book.save();
            }
        });
    }

save():保存对表的修改

5.修改数据

方法一:
修改onClick()中的代码如下:

public void onClick(View view) {
                Book book = new Book();
                book.setName("Android");
                book.setAuthor("Jack");
                book.setPrice(30.00);
                book.save();
                //设置更新价格为20
                book.setPrice(20.00);
                book.save();
            }

方法二(常用):

public void onClick(View view) {
                Book book = new Book();
                //更新的数据
                book.setPress("MingRi");
                //更新
                book.updateAll("name=? and author=?","Android","Jack");
            }

updateAll(String… conditions):修改表中的数据。参数为约束条件。若不指定约束条件表示修改所有数据。
setToDefault(String fieldName):设置字段为默认值。参数为字段名

6.删除数据

方法一:直接调用已存储对象的delete()方法

delete():删除表中数据
方法二(常用):调用LitePal的deleteAll()方法

public void onClick(View view) {
                LitePal.deleteAll(Book.class,"price<?","20.00");
            }

deleteAll(Class<?> modelClass, String… conditions):删除表中的数据。

  • 第一个参数:指定删除哪张表中的数据。
  • 第二个参数:约束条件。若未指定约束条件,表示删除表中所有数据。

更新和删除数据的方法一只能对已存储对象进行操作,限制较大。
已存储对象:调用过save()方法的对象

7.查询数据

public void onClick(View view) {
                List<Book> books = LitePal.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 price is"+book.getPrice());
                    Log.d("MainActivity","book press is"+book.getPress());
                }

findAll(Class modelClass, long… ids):查询表中的数据,返回值是Book类型的list集合。参数是表名

其他查询方法
findFirst(Class modelClass) :查询表中的第一条数据

Book firstBook = DataSupport.findFirst(Book.class);

findLast(Class modelClass):查询表中的最后一条数据

Book lastBook = DataSupport.findLast(Book.class);

select(String… columns):指定查询哪几列的数据

List<Book> books = DataSupport.select("name","author").find(Book.class);

where(String… conditions):指定查询的约束条件

List<Book> book = DataSupport.where("price>?","30").find(Book.class);

order(String column):指定结果的排序方式
将查询的结果按书价从高到低排序:

List<Book> book = DataSupport.order("price desc").find(Book.class);

limit(int value):指定查询结果的数量
只查表中前三条数据:

List<Book> book = DataSupport.limit(3).find(Book.class);

offset(int value):指定查询结果的偏移量
查询表中第2、3、4条数据:

List<Book> book = DataSupport.limit(3).offset(1).find(Book.class);

查询Book表中第5-7行满足price>20的name、author、price这3列数据,并将结果按照页数升序排列:

List<Book> books = DataSupport.select("name","author","price")
.where("price>?","20.00")
.order("price")
.limit(3).offset(4)
.find(Book.class);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值