• Android持久化技术,好内存不如烂存储


    前言

    本文讲解Android中常用的持久化技术,包括SharedPreferences键值对存储方式、SQLite数据库持久化技术、LitePal开源数据库工具等。

    六、Android持久化技术,好内存不如烂存储

    6.1 持久化技术介绍

    数据持久化简单来说就是将内存中暂时存储的数据转存到设备的存储单元中,使得数据处于持久状态。
    Android系统提供了3中方式简单的实现数据持久化功能,即简单文件存储、SharedPreferences存储、数据库存储。

    6.2 简单文件存储方案

    简单文件存储就是以流的形式将数据存储到文件中,适用于简单的二进制数据,文本数据等。

    1. 保存数据到文件的示例代码
    private void savaData(String persistencePath,String content)
        {
            FileOutputStream outputStream=null;
            BufferedWriter bufferedWriter=null;
            try {
                File file = new File(persistencePath);
                outputStream=new FileOutputStream(file);
                bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream));
                bufferedWriter.write(content);
                bufferedWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            finally {
                try {
                    if (outputStream!=null)
                        outputStream.close();
                    if (bufferedWriter!=null)
                        bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 从文件中读取数据的示例代码
    private String readData(string persistencePath)
        {
            FileInputStream fis = null;
            BufferedReader br = null;
            StringBuilder data = new StringBuilder();
            try {
                fis = new FileInputStream(persistencePath);
                br=new BufferedReader(new InputStreamReader(fis));
                String line="";
                while ((line=br.readLine())!=null)
                    data.append(line);
            }catch (IOException e) {
                e.printStackTrace();
            }
            finally {
                try {
                    if (fis!=null)
                        fis.close();
                    if (br!=null)
                        br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return data.toString();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    6.3 SharedPreferences存储方案

    SharedPreferences采用键值对的方式存储多种数据类型的数据。SharedPreferences文件都存储在/data/data/< Package name>/shared_prefs/目录下。

    6.3.1 获取SharedPreferences对象的三种方式

    1. Context类中的getSharedPreferences(文件名,模式)方法
      文件名:作为SharedPreferences文件的文件名。
      模式:只有MODE_PRIVATE一种表示只有当前应用程序才可以对这个SharedPreferences进行读写。
      示例:getSharedPreferences(“data”, MODE_PRIVATE);

    2. Activity类中getPreferences(模式)方法
      这个方法默认将当前活动的类名作为SharedPreferences的文件名。
      示例: getPreferences(MODE_PRIVATE);

    3. PreferenceManager类下的静态方法getDefaultSharedPreferences方法
      这个方法自动使用当前应用程序的包名作为前缀命名SharedPreferences的文件名。
      示例: PreferenceManager.getDefaultSharedPreferences(this);

    6.3.2 使用SharedPreferences对象存储和读取数据

    1. 存储数据示例
    SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);//获取SharedPreferences 对象
    SharedPreferences.Editor edit = sharedPreferences.edit();//获取编辑对象
    //通过set方法存储各种类型的数据
    edit.putString("name","mekeater");
    edit.putInt("age",18);
    edit.putBoolean("sex",true);
    edit.apply();//保存数据到 /data/data/package name/shared_prefs/data.xml文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 读取数据示例
    SharedPreferences sharedPreferences = getSharedPreferences("data", MODE_PRIVATE);//获取SharedPreferences 对象
    //通过get方法读取数据
    String name = sharedPreferences.getString("name", "");//第二个参数是键不存在的情况下,作为默认值
    int age = sharedPreferences.getInt("age", 0);
    boolean sex = sharedPreferences.getBoolean("sex", false);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6.4 SQLite数据库存储方案

    上面讲到的不管是通过流方式将数据存储到文件中,还是说通过SharedPreferences以键值对形式将数据存储到文件中,都只是适合存储简单的数据,不适合逻辑复杂的数据。

    术业有专攻,数据库就是设计来存储具有复杂关系的数据的,那么如果要存储具有复杂关系的数据,我们应该采用数据库进行存储,而Android系统提供一个轻量级的SQLite数据库,用于存储复杂的数据。

    6.4.1 创建数据库

    SQLite提供了一个SQLiteOpenHelper帮助类,通过该类可以非常简单的对数据库进行创建和升级等,但该类是一个抽象类,因此我们首先需要创建一个自己的帮助类去继承它。

    1. 自定义数据库帮助类继承SQLiteOpenHelper,重写onCreate和onUpgrade两个方法,示例代码如下:
    public class MyDatabaseHelper extends SQLiteOpenHelper {
    
        private Context mContext;
    
        //创建Book表的SQL语句
        public static final String CREATE_BOOK_TABLE="create table Book(" +
                "id integer primary key autoincrement," +
                "author text," +
                "price real," +
                "pages integer," +
                "name text)";
        //删除Book表的SQL语句
        public static final String DROP_BOOK="drop table if exists Book";
    
        //创建Category表的SQL语句
        public static final String CREATE_CATEGORY_TABLE="create table Category(" +
                "id integer primary key autoincrement," +
                "category_name text," +
                "category_code integer)";
        
        //删除Category表的SQL语句
        public static final String DROP_CATEGORY="drop table if exists Category";
    
        public MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
            this.mContext=context;
        }
    
        //数据库不存在的前提下,创建数据库完成后会调用该方法
        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
            sqLiteDatabase.execSQL(CREATE_BOOK_TABLE);//执行SQL语句,创建Book表
            sqLiteDatabase.execSQL(CREATE_CATEGORY_TABLE);//执行SQL语句,创建Category表
        }
    
        //数据库版本发生变化的时候,创建数据库操作后,会调用该方法
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
            sqLiteDatabase.execSQL(DROP_BOOK);//执行SQL语句,删除Book表
            sqLiteDatabase.execSQL(DROP_CATEGORY);//执行SQL语句,删除Category表
            onCreate(sqLiteDatabase);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    1. 实例化自定义的数据库帮助类,并创建数据库,核心代码如下:
      创建的SQLite数据库文件存放在 data/data/package name/databases/目录下
    //参数1:context 参数2:数据库名 参数3:一般为null 参数4:数据库版本号
    MyDatabaseHelper dbHelper=new MyDatabaseHelper(this,"BookStore.db",null,1);
    //调用getWritableDatabase方法或者getReadableDatabase方法创建数据库(若数据不存在则创建,若已存着则直接获得已有数据库)
    SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
    
    • 1
    • 2
    • 3
    • 4

    6.4.2 添加数据

    核心示例代码如下:

    SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
    //以键值对存储数据
    ContentValues contentValues = new ContentValues();
    contentValues.put("name","我是如何成功的?");
    contentValues.put("author","mekeater");
    contentValues.put("pages",666);
    contentValues.put("price",99);
    //将键值对数据存储到Book表中
    writableDatabase.insert("Book",null,contentValues);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.4.3 更新数据

    核心示例代码如下:

    SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.put("price",16);
    //参数1:表名 参数2:键值对值 参数3:where语句 参数4 where语句中需要的参数值
    writableDatabase.update("Book",contentValues,"author = ?",new String[]{"sun"});
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6.4.4 删除数据

    核心示例代码如下:

    SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
    //参数1:表名 参数2:where语句 参数3 where语句中需要的参数值
    writableDatabase.delete("Book",null,null);
    
    • 1
    • 2
    • 3

    6.4.5 查询数据

    核心示例代码如下:

    SQLiteDatabase writableDatabase = dbHelper.getWritableDatabase();
    Cursor cursor = writableDatabase.query("Book", null, null, null, null, null, null);
    //Cursor cursor = writableDatabase.rawQuery("select * from Book", null);//不采用Sqlite提供的方法,直接采用SQL完成操作
    if (cursor.moveToFirst())
    {
    	do {
    		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(TAG, "==============="+name+"     "+author+"     "+pages+"     "+price+"===============");
        }while (cursor.moveToNext());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    query方法包含7个参数,各个参数的意义如下表所示:
    在这里插入图片描述

    6.4.6 直接只用SQL语句实现增删查改操作

    SQLiteDatabase类提供了execSQL方法直接执行SQL语句,也提供了rawQuery方法直接执行SQL查询语句。
    示例代码如下:

    db.execSQL ( "insert into Book (name,author,pages,price) values(?,?,?,?)",new String[] { "The Da Vinci Code","Dan Brown","454","16.96"});
    
    • 1

    6.5 SQL太麻烦?LitePal让你不用SQL语句也能操作数据库

    通过SQLite数据库提供的方法结合SQL语句,我们就能完成对数据的管理及操作,但是SQL语句一般比较复杂,麻烦,影响开发效率,那么有没有不使用SQL语句就能操作SQLite数据库的方法呢?

    有的!

    本节学习的LitePal开源库采用对象关系映射(ORM)模式实现将我们开发中常用的一些功能进行封装,使得我们可以不用编写SQL语句就可以完成建表及增删改查的操作。

    什么是对象关系映射呢?简单点说,我们使用的编程语言是面向对象语言,而使用的数据库则是关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射了。

    下面来应用一下你就懂了。

    7.1 配置LitePal

    7.1.1 下载LitePal包

    链接:https://pan.baidu.com/s/1QKpEFUtJ7-d9lgzWiBWIQg?pwd=agjx
    提取码:agjx

    7.1.2 创建libs文件夹,并将jar丢进去

    在这里插入图片描述

    7.1.3 创建assets资源文件夹,并创建litepal.xml配置文件

    在这里插入图片描述

    7.1.4 litepal.xml配置数据库名称,版本,映射的表对象

    示例配置如下:

    <?xml version="1.0" encoding="utf-8" ?>
    <litepal>
        <dbname value="BookStore"/> <!--数据库名-->
        <version value="2"/> <!--数据库版本-->
        <list>
            <mapping class="com.xiaomi.litepaltest.Book"/> <!--映射的表对象类-->
        </list>
    </litepal>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    7.2 通过LitePal创建和升级数据库

    7.2.1 创建映射对象(数据库中的表结构)

    如在在数据库中创建一张Book表,只需要定义一个Book类,然后在litepal.xml文件的< list>标签内添加这个类即可。如果要对这张表进行CRUD,则还需要这个类继承DataSupport,如创建一个可以进行CRUD的Book表,定义Book类如下:

    import org.litepal.crud.DataSupport;
    public class Book extends DataSupport {
        private int id;
        private String author;
        private double price;
        private int pages;
        private String name;
        private String press;
    
        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;
        }
    
        public String getPress() {
            return press;
        }
    
        public void setPress(String press) {
            this.press = press;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    7.2.2 创建数据库

    只需要进行任意一次数据库操作就完成了数据库的创建,如下示例代码是最简单的一次数据库操作,它就完成了数据库的创建。

     Connector.getDatabase();//创建数据库
    
    • 1

    升级数据库,只需要在litepal.xml文件中修改版本号即可。

    7.3 通过LitePal进行数据库的增删改查

    7.3.1 添加数据

    如为Book表添加数据,只需要创建Book对象,然后调用DataSupport的save方法即可,核心示例代码如下:

    Book book = new Book();
    book.setAuthor("mekeater");
    book.setName("人性的弱点解读");
    book.setPages(666);
    book.setPrice(99);
    book.setPress("Unknow");
    book.save();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.3.2 更新数据

    核心示例代码如下:

    Book book = new Book();
    book.setPrice(99.99);
    book.updateAll("author = ?","mekeater");
    
    • 1
    • 2
    • 3

    7.3.3 删除数据

    核心示例代码如下:

    DataSupport.deleteAll(Book.class,"price < ?","99.99");
    
    • 1

    7.3.4 查询数据

    核心示例代码如下:

    StringBuilder sb = new StringBuilder();
    List<Book> books = DataSupport.findAll(Book.class);
    for (Book book : books) {
    	String name = book.getName();
    	String author = book.getAuthor();
    	double price = book.getPrice();
    	String press = book.getPress();
    	sb.append(name+"    "+author+"    "+pages+"    "+price+"    "+press+"\r\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    参考书籍:第一行代码

    链接:https://pan.baidu.com/s/1aXtOQCXL6qzxEFLBlqXs1Q?pwd=n5ag
    提取码:n5ag

  • 相关阅读:
    机器学习(十八):随机搜索和XGBoost
    【面试题01】找出数组中的最长前缀
    MySQL监控主从复制
    1.3常规信息系统集成技术
    CentOS安装openjdk和elasticsearch
    ssm+共享图书管理系统 毕业设计-附源码151121
    Python 机器学习入门之K-Means聚类算法
    2022年在uniapp中引入vant Weapp
    轮播图的两种方法
    【前端升全栈】 五分钟了解Node.js
  • 原文地址:https://blog.csdn.net/qq_34720818/article/details/127972373