Skip to content

数据持久化

文件操作模式

  • Context.MODE_PRIVATE:私有(默认模式,每次写入都会覆盖原有内容)
  • Context.MODE_APPEND:追加(每次写入会在原有文件内容后追加数据)

SharedPreferences

接口类,用键值对的方式存放数据,以xml格式存在设备的/data/data/包名/shared_prefs/下。

允许存储六种数据类型:int、long、float、boolean、String和Set\

获取对象

SharedPreferences sp = this.getSharedPreferences("文件名",模式);

文件名不带后缀,this是Activity上下文对象,如果不在Activity内调用需要手动获取。

模式只能用私有。

写入对象

  • 获取编辑器对象
    SharedPreferences.Editor editor =sp.edit();
    
  • editor.putXxx("参数名",参数值);
    
  • 提交
    1
    2
    3
    editor.apply();    //异步,推荐使用
    //or
    editor.commit();   //同步
    

读对象

Xxx obj =sp.getXxx("参数名",默认返回值);

移除对象

  • 获取编辑器对象
    SharedPreferences.Editor editor =sp.edit();
    
  • 移除一条数据
    editor.remove("参数名");
    
  • 清空所有数据
    editor.clear();
    
  • 提交

    同写入

文件存储

分为内部存储和外部存储。

内部存储

手机内存,仅能被应用程序自身访问,位于/data/data/包名/files/

  • 相关方法需要对可能的FileNotFoundException异常和IOException异常进行异常处理

    1
    2
    3
    4
    FileOutputStream fos=openFileOutput("文件名称",模式);     
    fos.write(写入的字符串.getBytes());
    fos.flush();      //从缓存写入
    fos.close();      //关闭输出流对象
    
  • 异常处理同上

    1
    2
    3
    4
    FileInputStream fis=openFileInput("文件名");
    byte[] content =new byte[fis.available()];
    fis.read(content);  
    fis.close();          
    

外部存储

SD卡类似的存储介质,位于手机外部存储空间中(通常可以通过文件管理器查看)。

  • 判断SD卡状态: 在读写外部存储前,应判断SD卡是否插入且可读写:
    Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    
  • 获取SD卡绝对路径:
    String path = Environment.getExternalStorageDirectory().getAbsolutePath();
    
  • 开启SD卡权限: 需要在 AndroidManifest.xml 中配置权限:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    

    对于 Android 6.0 及其以上版本,还需要在代码中动态申请权限。

SQLite数据库存储

轻量级关系数据库,支持NULL、REAL(浮点数)、INTEGER(整数)、TEXT(字符串文本)和BLOB(二进制对象),存储在后缀为db的文件里,路径为/data/data/包名/databases/目录下

创建数据库

  • 自定义继承SQLiteOpenHelper的类
  • 重写构造方法
    1
    2
    3
    4
    5
    class ClassName extends SQLiteOpenHelper{
        public ClassName(Context context){
            super(context,"databaseName.db",null,版本号);
        }
    }
    
  • 重写onCreate方法

    用于初次生成数据库时创建表:

    1
    2
    3
    4
    @Override
    public void onCreate(SQLiteDatabase db){
        // 通常在此处执行 db.execSQL() 来创建表
    }
    
  • 重写onUpgrade方法

    在数据库存在且版本号发生变化后调用:

    1
    2
    3
    4
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        // 用于更新表结构或数据迁移
    }
    
  • 在Activity中实例化自定义类
    1
    2
    3
    4
    5
    6
    ClassName obj =new ClassName(context);
    // 可读写,磁盘满时可能抛出异常
    SQLiteDatabase db1=obj.getWritableDatabase();    
    //or
    // 正常情况下可读写,磁盘满时以只读方式打开
    SQLiteDatabase db1=obj.getReadableDatabase();    
    

数据库的增删查改

有两种实现方式:执行SQL原生语句或使用Android提供的API方法。

  • 在Activity中实例化类并获取 SQLiteDatabase 对象。

方式一:使用 SQL 语句处理

  • 增、删、改(非查询操作)

    使用 execSQL() 方法:

    db.execSQL("insert/update/delete 语句", new Object[]{参数列表});
    
  • 查(查询操作)

    使用 rawQuery() 方法:

    Cursor cursor = db.rawQuery("select 语句", new String[]{参数列表});
    

方式二:使用 Android 提供的 API

此类操作中,增和改需要借助 ContentValues 对象来封装键值对数据(键为列名,值为数据)。

  • 增(insert)
    1
    2
    3
    ContentValues values = new ContentValues();
    values.put("列名", );
    db.insert("表名", null, values);
    
  • 改(update)
    1
    2
    3
    ContentValues values = new ContentValues();
    values.put("列名", 新值);
    db.update("表名", values, "条件如 id=?", new String[]{"条件值"});
    
  • 删(delete)
    db.delete("表名", "条件如 id=?", new String[]{"条件值"});
    
  • 查(query)
    Cursor cursor = db.query("表名", new String[]{"列名1", "列名2"}, "条件如 id=?", new String[]{"条件值"}, null, null, "排序方式");
    

Cursor 游标使用方法

无论用哪种查询方式,返回的都是一个 Cursor 游标对象,用于遍历结果集:

1
2
3
4
5
6
while(cursor.moveToNext()){
    // 根据列名获取索引位置,再根据位置获取对应类型的数据
    String data = cursor.getString(cursor.getColumnIndex("列名"));
    int id = cursor.getInt(cursor.getColumnIndex("id"));
}
cursor.close(); // 查询结束后必须关闭游标