Android数据持久化,你还不会?

嘚吧嘚

数据持久化是开发过程中不可避免的,因为数据是核心,是非常重要的。

总结一下常用的数据持久化的方式:

  • SharedPreferences存储数据
  • 文件存储数据
  • SQLite数据库存储数据
  • ContentProvider存储数据

话不多说,上干货。

SharedPreferences(共享首选项)

适用范围:
保存少量的数据,且这些数据的格式非常简单(基本数据类型)。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口令密码等
核心原理:
数据的保存形式是基于XML文件存储的key-value键值对,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data//shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储和修改是通过SharedPreferences.edit()获取的嵌入类Editor实现。

获取首选项对象

SharedPreferences sp = getSharedPreferences(String name, int mode);

参数:
name: 首选项文件的名称
mode: 首选项文件打开模式
   MODE_PRIVATE 只能在本应用程序读写
   MODE_WORLD_READABLE 能被其他应用读
   MODE_WORLD_WRITEABLE 能被其他应用读写

通过嵌入类Editor写数据

//获取嵌入类Editor
SharedPreferences.Editor edit = sp.edit();
//写数据
edit.putXXXX(String key, value);
//提交
edit.commit();

在这里插入图片描述
切记,切记,写完数据之后一定要提交,否则首选项文件不会保存数据
来看一下官方开发文档中的介绍:

在这里插入图片描述

简单翻译一下:
提交从编辑首选项对象的编辑器返回的首选项文件中的改变(大体就是这个意思,若是翻译的不好,大佬勿喷🙈)


翻译过来有点绕,断一下句好理解一些了:
提交 / 从 / 编辑首选项对象的编辑器 / 返回的 / 首选项文件中的改变
不提交就不会保存数据的更改

从首选项文件获取数据

SharedPreferences.getXXXX(String key, defaultvalue);

在这里插入图片描述

学以致用

layout布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="信息" />

</LinearLayout>

核心代码:

/*
 * 获得 共享首选项对象(p1:文件名,p2:读写模式)
 * 只有当前程序对test进行读写(test不存在时会自动创建)
 */
SharedPreferences sp = getSharedPreferences("test", MODE_PRIVATE);
/*
 * 写数据,通过嵌套类Editor写数据
 * 写数据,保存在内存中没有加入磁盘中
 */
SharedPreferences.Editor edit = sp.edit();
edit.putString("姓名", "张三");
edit.putInt("年龄", 21);
edit.putBoolean("性别", true);
//提交数据
edit.commit();

//读取数据
String str = "姓名:" + sp.getString("姓名", "") +
             ",年龄:" + sp.getInt("年龄", 0) +
             ",性别:" + sp.getBoolean("性别", true);

Button msgBtn = findViewById(R.id.msg);
        msgBtn.setOnClickListener((v) -> {
            Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
        });

效果图:

在这里插入图片描述

文件存储数据(File Java I/O)

将数据写入文件

核心代码

FileOutputStream fos = openFileOutput(fileName, mode);
fos.write(message.getBytes());
fos.close();

参数:
fileName: 数据待写入的文件名称
mode:文件打开模式
   MODE_PRIVATE: 为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把
            新写入的内容追加到原文件中。可以使用MODE_APPEND
   MODE_APPEND: 模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
   MODE_WORLD_READABLE: 表示当前文件可以被其他应用读取
   MODE_WORLD_WRITEABLE: 表示当前文件可以被其他应用写入

从文件中读出数据

核心代码

//fileName为待读取数据的文件的名称
FileInputStream inStream = openFileInput(fileName);
byte[] buffer = new byte[1024];
int len = 0;
StringBuilder sb = new StringBuilder();
//从文件中读取数据
while ((len = inStream.read(buffer)) != -1) {
        sb.append(new String(buffer, 0, len));
}
//关闭输入流
inStream.close();
//转化为字符串
str = sb.toString();

学以致用

在这里插入图片描述
首先将写入数据和读取数据的方法写好。

    /**
     * 读出文件中的数据
     *
     * @param fileName 文件的名称
     * @return 读出的数据
     */
    public String read(String fileName) {
        try {
            //创建一个FileInputStream对象
            FileInputStream inStream = openFileInput(fileName);
            byte[] buffer = new byte[1024];
            int len = 0;
            StringBuilder sb = new StringBuilder();
            //从文件中读取数据
            while ((len = inStream.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }
            //关闭输入流
            inStream.close();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 向文件中写入数据
     *
     * @param message  待写入的数据
     * @param fileName 文件名称
     * @param mode     打开文件的模式
     */
    public void write(String message, String fileName, int mode) {
        //获取输入值
        if (message == null)
            return;
        try {
            //创建一个FileOutputStream对象,mode为文件打开的模式
            FileOutputStream fos = openFileOutput(fileName, mode);
            //将获取过来的值放入文件
            fos.write(message.getBytes());
            //关闭输出流
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

layout布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/msg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="信息" />

    <Button
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="商店" />

</LinearLayout>

MainActivity主要代码(实际开发中不能这么写,只作为演示用)

write("篮球:10个\n排球:5个\n羽毛球:6个\n", "message.txt", MODE_PRIVATE);
Button info = findViewById(R.id.info);
info.setOnClickListener((v) -> {
    String read = read("message.txt");
    Toast.makeText(MainActivity.this, read, Toast.LENGTH_SHORT).show();
});

效果图:

在这里插入图片描述

SQLite数据库存储数据

SQLite是轻量级嵌入式数据库引擎,它支持SQL语言,并且只利用很少的内存就有很好的性能。在我们为移动设备开发应用程序时,也许就要使用到SQLite,所以我们就需要掌握移动设备上的SQLite开发技巧。

使用SQLite数据库需要自定义一个类继承SQLiteOpenHelper帮助类来创建和升级数据库。

在这里插入图片描述
提供一个简单的模板,如下:

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyHelper extends SQLiteOpenHelper {
    Context myContext;//上下文对象

    /**
     * @param context 上下文对象
     * @param name    数据库名称
     * @param factory 游标工具类,用null
     * @param version 数据库版本,整数
     */
    public MyHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        myContext = context;
    }

    //第一次创建数据库时调用,如果数据库已经存在,就不在调用
    @Override
    public void onCreate(SQLiteDatabase db) {
        //创建一个学生表吧
        String createTable = "create table student ("
                + "id integer primary key autoincrement,"
                + "sNumber text,"
                + "sName text,"
                + "sAge text)";

        db.execSQL(createTable);//创建数据库表
        Toast.makeText(myContext, "学生表创建完毕!", Toast.LENGTH_LONG).show();
    }

    //数据库版本变化时,会调用onUpgrade()
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //你的代码
    }
}

使用数据库类SQLiteDatabase对数据库进行CRUD操作
伪代码如下:

MyHelper helper = new MyHelper(MainActivity.this, "stud.db", null, 1);
SQLiteDatabase database = helper.getWritableDatabase();

//增 在数据库例添加几条数据
ContentValues values = new ContentValues();//ContentValue:封装表中一行,用来添加或修改数据表
cv.put("sNumber","2018001");
cv.put("sName", "Tom");
cv.put("sAge", "21");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018002");
cv.put("sName", "Tom");
cv.put("sAge", "22");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018003");
cv.put("sName", "Tom");
cv.put("sAge", "19");
database.insert("student", null, cv);
cv.clear();

cv.put("sNumber","2018004");
cv.put("sName", "Jack");
cv.put("sAge", "21");
database.insert("student", null, cv);
cv.clear();

//删 删除名字叫“Tom”,年龄为22岁的数据
int delete = database.delete("student", "sName = ? and sAge = ?", new String[]{"Tom", "22"});
System.out.println("res = " + delete);

//改 修改名字叫“Tom”,年龄为21岁的数据,把名字修改为“Tom2”
values.put("sName", "Tom2");//修改的数据
int update = database.update("student", values, "SName = ? and sAge = ?", new String[]{"Tom", "21"});
cv.clear();
System.out.println("res = " + update);

//查 查询所有数据
Cursor stu = database.query("student", null, null, null, null, null, null);//Cursor:游标类,封装查询结果
if (stu.moveToFirst()) {
    do {
        String sNumber = stu.getString(stu.getColumnIndex("sNumber"));
        String sName = stu.getString(stu.getColumnIndex("sName"));
        String sAge = stu.getString(stu.getColumnIndex("sAge"));

        System.out.println("id:" + sNumber + "\t,name:" + sName + "\t,age:" + sAge);
    } while (stu.moveToNext());
} else {
    System.out.println("没找到");
}

ContentProvider存储数据

内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,不同于文件存储和SharedPreferences存储中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险

详细内容请参考文章《内容提供器ContentProvider

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章