技术经验谈 技术经验谈
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

hss01248

一号线程序员
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 最佳实践

    • Android数据库操作最佳实践
      • 一般的使用方式:
      • 升级不清库
    • 基于蒲公英平台的app发布,更新,反馈功能的实现
    • testRss
  • ui

  • 优化

  • aop

  • apm

  • 架构

  • webview

  • rxjava

  • activity-fragment-view的回调和日志
  • Android加密相关
  • Android命令行操作
  • app后台任务
  • kotlin
  • kotlin漫谈
  • kotlin语言导论
  • sentry上传mapping.txt文件
  • so放于远程动态加载方案
  • states
  • Xposed模块开发
  • 一个关于manifest合并的猥琐操作
  • 玩坏android存储
  • 获取本app的安装来源信息
  • Android
  • 最佳实践
hss01248
2022-01-18
目录

Android数据库操作最佳实践

# Android数据库操作最佳实践

推荐使用greendao, 完全orm操作, 也支持手写sql.

数据库查看使用加强版的flipperUtil. 可查看sd卡上的任意数据库文件.

# GreenDao工具链

# 基本使用

工程根build.gradle里添加插件

buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0'
    }
}
1
2
3
4
5
6
7
8
9
10
11

app或library里添加依赖,插件,配置:

示例:

dependencies {
    api 'org.greenrobot:greendao:3.3.0'
    implementation "net.zetetic:android-database-sqlcipher:4.4.3"//数据库加密, 在Android5 vivo上会崩溃.其他问题未发现.
    api "androidx.sqlite:sqlite:2.0.1"
    api 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1'//数据库升级不清库
}
apply plugin: 'org.greenrobot.greendao'
greendao {
    schemaVersion 1 //数据库版本号
    daoPackage 'com.hss01248.accountcache.db'
// 设置DaoMaster、DaoSession、Dao 包名
    targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录,请注意,这里路径用/不要用.
    generateTests false //设置为true以自动生成单元测试。
    targetGenDirTests 'src/main/java' //应存储生成的单元测试的基本目录。默认为 src / androidTest / java。
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 一般的使用方式:

public class MyDbUtil {

    /**
     * 初始化GreenDao,直接在Application中进行初始化操作
     */
    private static void initGreenDao(Application context) {
        DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(context, "xxx.db");
        Database db = helper.getWritableDb();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }


  private static DaoSession daoSession;
    //对外提供的api
  public static DaoSession getDaoSession() {
      if(daoSession ==null){
          initGreenDao(AccountCacher.app);
      }
      return daoSession;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 升级不清库

默认的DaoMaster.DevOpenHelper升级时会清空数据:

public void onUpgrade(Database db, int oldVersion, int newVersion) {
    Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
    dropAllTables(db, true);
    onCreate(db);
}
1
2
3
4
5

所以需要用不清库的操作: 构建一个自己的DaoMaster.OpenHelper:

dependencies {
    api 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1'//数据库升级不清库
}
1
2
3
public class MySQLiteUpgradeOpenHelper extends DaoMaster.OpenHelper {
    public MySQLiteUpgradeOpenHelper(Context context, String name) {
        super(context, name);
    }

    public MySQLiteUpgradeOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                DaoMaster.createAllTables(db, ifNotExists);
            }
            @Override
            public void onDropAllTables(Database db, boolean ifExists) {
                DaoMaster.dropAllTables(db, ifExists);
            }
        }, DebugAccountDao.class);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 把数据库保存到sd卡的其他目录下:

public class MyDBContext extends ContextWrapper {

    public MyDBContext(Context base) {
        super(base);
    }

    /**
     * 获得数据库路径,如果不存在,则自动创建
     */
    @Override
    public File getDatabasePath(String name) {
        //判断是否存在sd卡
        boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState());
        if(!sdExist){//如果不存在,
            Log.e("SD卡管理:", "SD卡不存在,请加载SD卡");
            return null;
        }
        else{//如果存在
            //获取sd卡路径
            String dbDir=android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
            dbDir += "/.yuv/databases";//数据库所在目录
            String dbPath = dbDir+"/"+name;//数据库路径
            //判断目录是否存在,不存在则创建该目录
            File dirFile = new File(dbDir);
            if(!dirFile.exists()) {
                dirFile.mkdirs();
            }
            //数据库文件是否创建成功
            boolean isFileCreateSuccess = false;
            //判断文件是否存在,不存在则创建该文件
            File dbFile = new File(dbPath);
            if(!dbFile.exists()){
                try {
                    isFileCreateSuccess = dbFile.createNewFile();//创建文件
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                isFileCreateSuccess = true;
            }
            //返回数据库文件对象
            if(isFileCreateSuccess) {
                return dbFile;
            } else {
                return null;
            }
        }
    }

    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
                                               SQLiteDatabase.CursorFactory factory) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
        return result;
    }

    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory,
                                               DatabaseErrorHandler errorHandler) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
        return result;
    }

}
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
58
59
60
61
62
63
64

# 数据库加密

使用sqlspher:

dependencies {
    implementation "net.zetetic:android-database-sqlcipher:4.4.3"//数据库加密
}
1
2
3
  Database db = helper.getEncryptedWritableDb("密码");
1

# 综合以上三个功能,如下:

public class MyDbUtil {

    /**
     * 初始化GreenDao,直接在Application中进行初始化操作
     */
    private static void initGreenDao(Application context) {
        //MyDBContext内部指定数据库存储路径
       Context context2 = new MyDBContext(context);
       //升级自动迁移数据的工具
        DaoMaster.OpenHelper helper = new MySQLiteUpgradeOpenHelper(context2, "xxx.db");
        //加密.但是sqlitesipher在6.0以下版本的vivo等机型上有c层崩溃问题
      Database db = helper.getEncryptedWritableDb("密码");
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 数据库查看:

应用内部数据库可使用glance(纯手机端)或flipper或Android studio查看

sd卡根目录数据可使用flipperUtil查看

https://github.com/guolindev/Glance

https://github.com/hss01248/flipperUtil

# 示例代码位置

https://github.com/hss01248/accountCacher/blob/master/accountcache/build.gradle

编辑 (opens new window)
上次更新: 2022/08/25, 20:20:31
基于蒲公英平台的app发布,更新,反馈功能的实现

基于蒲公英平台的app发布,更新,反馈功能的实现→

最近更新
01
截图后的自动压缩工具
12-27
02
图片视频文件根据exif批量重命名
12-27
03
chatgpt图片识别描述功能
02-20
更多文章>
Theme by Vdoing | Copyright © 2020-2025 | 粤ICP备20041795号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式