Android APP完整基础教程(18)存储

42 篇文章 14 订阅

1 SharedPreferences和Editor

@1 SharedPreferences和SharedPreferences.Editor解读

SharedPreferences用于存储类似配置信息的内容,主要是简单的键值对(key-value)

对于数据存储,无非是 读和写。关于SharedPreferences存储数据:

  • SharedPreferences本身用于读取(getXXX(key,defvalue))数据。没有关于写数据的方法。
  • SharedPreferences通过edit()方法获取Editor对象用于写入数据(putXXX(key,value))。

SharedPreferences是接口,无法直接创建,需通过Context的getSharedPreferences()方法获取。

@2 SharedPreferences使用解读

//定义
SharedPreferences sharedPreferences;
SharedPreferences.Editor edit;

//获取SharedPreferences,参数Context.MODE_PRIVATE表示该数据只能被本程序读写
sharedPreferences = getSharedPreferences("ags", Context.MODE_PRIVATE);

//写入数据
edit = sharedPreferences.edit();
edit.putFloat("floatValue",3.14f);
edit.putBoolean("BooleanValue",true);
edit.putString("StringValue","AGSTestStringValue");
edit.apply();//提交数据

//读取数据
float floatValue = sharedPreferences.getFloat("floatValue",0.0f);
Boolean boolValue = sharedPreferences.getBoolean("BooleanValue",false);
String stringValue = sharedPreferences.getString("StringValue","");

关于数据提交的说明:

  • apply() 不会阻塞前台线程,后台提交修改。
  • commit方法会阻塞前台线程但会立即生效。

@3 SharedPreferences存储路径

SharedPreferences数据存储在/data/data/<应用包名>/shared_prefs目录下,以xml格式保存,内容为键值对(key-value)。

@4 SharedPreferences官方文档

2 IO流 文件存储

2.1 APP内部文件存储

@1 文件存储基础

关于Android的文件存储,我们关注 打开/关闭、读/写,实际上和java原生的IO体系类似,尤其是读写,都是read/write。因此这里简述文件和文件夹的打开/关闭(主要针对APP内文件存储)

@2 使用解读

关于文件,Context本身提供2个关键API(openFileOutput和openFileInput),使用如下所示:

//1 定义输入流
FileInputStream fileInputStream = null;
//打开操作,注意try catch
try {
    //打开应用程序 数据文件夹下的test文件 输入流
    fileInputStream = openFileInput("test");
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
//关闭操作,注意try catch
if(fileInputStream!=null) {
    try {
        fileInputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

//2 定义输出流
FileOutputStream fileOutputStream = null;
//打开操作,注意try catch
try {
    //打开应用程序 数据文件夹下的test文件 输出流
    //参数MODE_PRIVATE表示只能被当前程序读写,如果改为MODE_APPEND则表示追加内容
    fileOutputStream = openFileOutput("test",MODE_PRIVATE);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
//关闭操作,注意try catch
if(fileOutputStream!=null){
    try {
        fileOutputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

关于文件夹,Context本身提供的关键API。使用如下所示:

//常见文件夹操作
File fileDir = getDir("dirtest",MODE_PRIVATE); //获取文件夹dirtest句柄
File fileDir2 = getFilesDir(); //获取应用程序 数据文件夹的绝对路径
String[] dir = fileList();//列出应用程序 数据文件夹下的 全部文件
deleteFile("filetest");//删除应用程序 数据文件夹下的 指定文件 filetest

//常见文件夹路径整理
getCacheDir().getAbsolutePath();   //路径 /data/user/0/<应用包名>/cache    
getFilesDir().getAbsolutePath();   //路径 /data/user/0/<应用包名>/files
getExternalCacheDir().getAbsolutePath(); //路径 /storage/emulated/0/Android/data/<应用包名>/cache
getExternalFilesDir(null).getAbsolutePath(); //路径 /storage/emulated/0/Android/data/<应用包名>/files

@3 文件操作的权限

在SD卡上存储文件均需在AndroidManifest.xml文件中添加权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

@4 存储路径

数据存储在/data/data/<应用包名>/files 文件夹下。

@5 Context中 数据文件/文件夹 官方文档

注意:虽然很多文件操作 我们是通过Context来获取文件的相关API,但这些API实际上是定义在ContextWrapper类中的,详细解读如下:Android ContextWrapper类详解

2.2 APP外 文件存储

以上所涉及的是针对应用程序内数据文件/文件夹的相关操作。如果需要访问SD卡,则需要:

//获取SD卡目录的路径
String sdcardDir = Environment.getExternalStorageDirectory();

关于权限,如果需要创建/删除文件,那么还需要 挂载/卸载 权限(注意:系统APP),如下所示:

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

注意:在Android Q中该方法已被弃用,在Android Q之后不推荐使用该方法,如果要使用,需在权限之外 在 application节点中添加。

android:requestLegacyExternalStorage="true"

如果不使用该方法也可以,参照(引自 Android解决getExternalStorageDirectory在29后废弃问题)代码:

//通过APP所在路径 层层回滚到上级目录,直到Android,然后再拼接
File externalFileRootDir = getExternalFilesDir(null);
do {
    externalFileRootDir = Objects.requireNonNull(externalFileRootDir).getParentFile();
} while (Objects.requireNonNull(externalFileRootDir).getAbsolutePath().contains("/Android"));

String saveDir = Objects.requireNonNull(externalFileRootDir).getAbsolutePath();
String savePath = saveDir + "/" + Environment.DIRECTORY_DCIM + "/" + filename;

3 数据库Sqlite简介(关键接口说明)

Android集成了轻量级Sqlite数据库,本质上是一种更加便捷的文件操作。关于这部分,首先回顾下数据库的基础知识:SQLite 简介 | 菜鸟教程。有了这个基础,加上本质上Android是对数据库Sqlite集成,因此该部分内容更依赖于对数据库的理解,该部分主要是对封装的关键类进行解读。

3.1 SQLiteDatabase类解读 

SQLiteDatabase类既代表与数据库的连接,又可用于执行sql语句。相关操作整理如下:

//1 打开/创建数据库,从文件 或者 路径中读取数据库
/*flags解读:
 *OPEN_READONLY :只读方式打开数据库(常量值为1)
 *OPEN_READWRITE:读写方式打开数据库(常量值为0)
 *CREATE_IF_NECESSARY:数据库不存在时创建数据库
 *NO_LOCALIZED_COLLATORS:打开数据库时不根据本地化语言对数据库进行排序(常量值为:16)
 */
static SQLiteDatabase openOrCreateDatabase (File file,SQLiteDatabase.CursorFactory factory)
static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags, DatabaseErrorHandler errorHandler);
static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags);
static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler);
static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory);

//2 执行SQL语句
execSQL(String sql , Object[] args);    //执行带占位符的sql语句
//Android考虑到有不熟悉sql语句的开发者,提供了进一步封装后的一系列方法,即:
long insert(String table,String nullColumnHack,ContentValues  values);//插入记录
int delete(String table,String whereClause,String[]  whereArgs);//删除一条记录
Cursor query(String table,String[] columns,String selection,String[]  selectionArgs,String groupBy,String having,String  orderBy);//查询一条记录
Cursor rawQuery (String sql,String[] selectionArgs,CancellationSignal cancellationSignal);//查询一条记录,sql语句模式
int update(String table,ContentValues values,String whereClause,String[]  whereArgs);//修改记录

//事物开始/结束
beginTransaction();//开始事务
endTransaction();  //结束事务
inTransaction();   //处于事务上下文中,处于返回true,不处于返回false。

注意:rawQuery直接使用SQL语句进行查询,在第一个参数字符串内的“?”会被后面的String[]数组逐一对换掉;而query函数是Android自己封装的查询API,在实际使用场景中,query方法更不容易出错。

关于,更多详细内容查看官方文档:Android SQLiteDatabase类详解

3.2 SQLiteOpenHelper类解读

在真实的项目中更多的是使用工具类SQLiteOpenHelper来创建数据库 而不是使用SQLiteDatabase的openXXX方法来获取数据库的句柄(SQLiteOpenHelper是SQLiteDatabse的一个帮助类,用来管理数据的创建和版本更新,可以理解为对SQLiteDatabase的一种封装)。这里主要介绍SQLiteOpenHelper 打开数据库的方法。先定义一个子类,代码如下所示:

public class DbOpenHelper extends SQLiteOpenHelper {   
    public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
                        int version) {
        super(context, name, null, 1);
    }
    @Override //第1次创建时调用
    public void onCreate(SQLiteDatabase db) {

    }
    @Override //数据库升级时自动调用
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

之后 使用该对象,如下所示:

//1 打开数据库
DbOpenHelper dbOpenHelper = new DbOpenHelper(MainActivity.this,"testDB",null,1);
//创建/打开 可读数据库
SQLiteDatabase sqLiteDatabaseR = dbOpenHelper.getReadableDatabase();
//创建/打开 可读写数据库
SQLiteDatabase sqLiteDatabaseRW = dbOpenHelper.getWritableDatabase();

//2 关于数据库操作:使用SQLiteDatabase的操作SQl的方式 或 封装的增删改查方法均可。

//3 关闭数据库,一次性关闭dbOpenHelper中所有的SQLiteDatabase类型句柄。
dbOpenHelper.close();

关于,更多详细内容查看官方文档:Android SQLiteOpenHelper类详解

3.3 Android的 sqlite3 命令

执行adb shell,进入到终端,然后执行:

$cd data/data/<project_name>/databases
$ls   

列出数据库文件,接下来进入数据库,比如:

$sqlite3 test_db

显示如下内容:接下来可以对数据库进行命令行操作

SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>

常见sqlite3使用语句如下:

>.databases ----产看当前数据库
>.tables    ----查看当前数据库中的表
>.help      ----帮助信息,所有命令的解读

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值