添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

存储目录: /data/data/<packagename>/shared_prefs/ 轻量级存储,本地目录在,在正式发布的版本上,只有root才能看到。

什么是轻量? 对其环境依赖的越少,就越轻量,也就是减少耦合的意思。

  • SQLite
  • 存储目录: /data/data/<package name>/databases/ SQLite 是一个微型数据库,效率高,特别适合存储结构化的数据。Android 中内置了SQLite数据库,它支持SQL语法,但在Android中一般不直接写SQL语句,而是使用第三方库操作对象,达到对数据库增删改查的目的,比如 GreenDao。

  • ContentProvider
  • ContentProvider 是Android存储数据的方案,底部仍然是使用SqLite。它根据Uri(Universal Resource Identifier)统一资源定位符 确定资源。可以多app使用,比如通讯录可以给多个应用获取。虽然日常开发中对 ContentProvider 使用不多,但和 ContentProvider 的接触却很频繁,比如 选择一张图片,我们首先拿到的却是Uri。

    文件存储,分为内部存储和外部存储。

  • 怎么区分内部存储和外部存储?
  • 对用户而言可插拔的SD卡就是外部存储,焊接在手机内部的就是内部存储。

    但对于开发者而言并不是这样。

    在该应用目录下的存储是内部存储。

    反之即使存在手机不可拆卸的存储卡上,也叫外部存储。

  • 内部存储和外部存储有哪些不同?
  • (1) 在 /data/data/package_name 目录下,在debug环境下,可以通过 AndroidStudio Device File Explorer 查询到该app的存储,如果需要查询其它app的这个目录,则需要Root。 (2) 内部存储在应用卸载的时候会被清除,而外部存储不会。 (3) 操作内部存储目录不需要申请存储权限,而外部存储需要存储权限。这点也能理解,操作自己的应用不需要过多干预提醒。

    文件保存在服务器上,通过url操作服务器上的资源。比如apk的版本更新下载apk的场景。

    二、拓展的存储方式

  • GreenDao-操作对象即修改数据
  • ACache-一个类轻松缓存
  • ImageLoader/Glide-缓存图片
  • 三、缓存设计

    “我想缓存一张图片”

    使用三级缓存。网络缓存(速度慢、费流量), 本地缓存,内存缓存。

    首次网络加载时缓存到本地存储,缓存到内存; 当再次访问该图片时,

    graph TD
    再次加载该图片时 --> C{内存中是否存在}
    C -->|存在| D[显示图片]
    C -->|不存在| E{本地文件是否存在}
    E -->|存在| X[显示图片]
    E -->|不存在| F[请求网络]
    F --> Y[显示图片]
    

    “我想加载新闻内容”

    使用ACache 缓存新闻内容,在下次加载时先请求本地的缓存,然后后台请求网络,请求网络数据成功后再去更新页面。

    graph TD
    A[开始] -->|start| B(加载新闻)
    B --> C{本地缓存是否存在}
    C -->|是| D[显示缓存的内容]
    D --> E
    C -->|否| E[后台请求网络数据]
    E -->|拿到数据| F[显示/刷新页面]
    

    由于新闻的数据不需要与服务器保持高度统一,所以这里我们将新闻数据放入ACache中,ACache 也可以轻松的设置过期时间。

    “我想在app存一万条人员信息”

    当有大量数据时,如果我们把数据用JSON存在SP 或者 文件里,对单条信息的操作却要读取整个文件,这样明显是不值得的。

    再看看Sqlite的有点

    "适合存储结构化的数据"

    那么人员信息就应该依据ID、姓名、性别、年龄等字段在Sqlite中建表。

    这样在对单个数据操作时就可以通过ID进行操作。

    四、GreenDao实践

    明确GreenDao的核心类含义

    DaoMaster: DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper是SQLiteOpenHelper实现,它们在SQLite数据库中创建模式。

    DaoSession:管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取该对象。DaoSession还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。

    XXXDao:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO生成DAO。它具有比DaoSession更多的持久性方法,例如:count,loadAll和insertInTx。

    Entities :可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。

    1. 创建好输入框按钮等界面

    2. 然后添加配置信息配置信息最好根据github上的地址指引去做,因为会经常保持更新。

    github.com/greenrobot/…

    Add the following Gradle configuration to your Android project. In your root build.gradle file:
    buildscript {
        repositories {
            jcenter()
            mavenCentral() // add repository
        dependencies {
            classpath 'com.android.tools.build:gradle:3.1.1'
            classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    In your app modules app/build.gradle file:
    apply plugin: 'com.android.application'
    apply plugin: 'org.greenrobot.greendao' // apply plugin
    dependencies {
        implementation 'org.greenrobot:greendao:3.2.2' // add library
    

    然后在app/build.gradle 中的根目录添加greenDao的配置信息。

    //数据库配置
    greendao {
        //数据库版本号
        schemaVersion 1
        //自动生成代码所在的包名
        daoPackage 'com.dao.green.db'
        targetGenDir 'src/main/java'
    

    3. 创建实体类

    @Entity(nameInDb = "STUDENT") //添加该行,代表自动生成
    public class Student {
        @Id(autoincrement = true)
        @Unique
        private Long id; //主键自增长,不可重复,作为不同记录对象的标识,传入参数对象时不要传入
        @Property(nameInDb = "name")
        private String name; //名字
        @Property(nameInDb = "mark")
        private String mark; //备注
    

    创建完成后,编译之后会自动在相应目录下生成master、session、dao文件。

    4. 在自定义的Application中初始化

    GreenDaopublic class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            //打开数据库
            DbManager.getInstance().initDb(this);
    

    5. 重写MySqliteOpenHelper,防止数据库升级清空本地数据

    public class MySqliteOpenHelper extends DaoMaster.DevOpenHelper {
        public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
            super(context, name, factory);
         * 需要在实体类加一个字段 或者 改变字段属性等 就需要版本更新来保存以前的数据了
         * @param db
         * @param oldVersion
         * @param newVersion
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            super.onUpgrade(db, oldVersion, 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);
            }, StudentDao.class);
    

    MigrationHelper.java 来自github:github.com/yuweiguocn/…

    6. 封装DbManager、DbHelperDbManager

     * @author by T, Date on 2019-10-22.  * note: DB的管理类 public class DbManager {     //数据库名称     private static final String DATABASE_NAME = "student_data";     private static DbManager instance;     private DaoSession mDaoSession;     private DaoMaster.DevOpenHelper mDevOpenHelper;     private DaoMaster mDaoMaster;      * 获取单例      * @return     public static DbManager getInstance() {         if (instance == null) {             synchronized (DbManager.class) {                 if (instance == null) {                     instance = new DbManager();         return instance;     public void initDb(Context context) {         mDevOpenHelper = new MySqliteOpenHelper(context, DATABASE_NAME, null);         mDaoMaster = new DaoMaster(mDevOpenHelper.getWritableDatabase());         mDaoSession = mDaoMaster.newSession();         LogUtils.d("打开了数据库:" + mDevOpenHelper.getDatabaseName());     public DaoSession getDaoSession() {         return mDaoSession;      * 关闭数据库 (思考:关闭数据库的场景在哪里)     public void closeDataBase() {         if (mDevOpenHelper != null) {             LogUtils.d("关闭了数据库" + mDevOpenHelper.getDatabaseName());         closeDaoSession();         closeHelper();     private void closeDaoSession() {         if (mDaoSession != null) {             mDaoSession.clear();             mDaoSession = null;     private void closeHelper() {         if (mDevOpenHelper != null) {             mDevOpenHelper.close();             mDevOpenHelper = null;

    DbHelper

     * @author by T, Date on 2019-10-22.  * note: 进一步封装,对外直接使用该类 public class DbHelper {      * 插入一条学生信息      * @param student      * @return     public static boolean insertStudentInfo(Student student) {         if (student == null) return false;         StudentDao studentDao = DbManager.getInstance().getDaoSession().getStudentDao();         try {             long index = studentDao.insertOrReplace(student);             LogUtils.d("id:" + index);             return true;         } catch (Exception e) {             return false;      * 查询所有的学生      * @return     public static List<Student> queryAllStudent() {         StudentDao studentDao = DbManager.getInstance().getDaoSession().getStudentDao();         try {             return studentDao.loadAll();         } catch (Exception e) {             return null;

    7. Activity中的使用Activity中的两个点击方法

         * 保存数据      * @param view     public void Save(View view) {         Student student = new Student();         student.setName(etName.getText().toString());         student.setMark(etMark.getText().toString());         boolean flag = DbHelper.insertStudentInfo(student);         LogUtils.d("插入是否成功:" + flag);      * 查询全部数据      * @param view     public void QueryAll(View view) {         List<Student> listStudents = DbHelper.queryAllStudent();         if (listStudents == null) {             LogUtils.d("没有数据");             return;         for (int i = 0; i < listStudents.size(); i++) {             LogUtils.d("id:" + listStudents.get(i).getId() + "_name:" + listStudents.get(i).getName()); 复制代码
    分类:
    Android
    标签: