美文网首页
GreenDao遇到的一些坑

GreenDao遇到的一些坑

作者: qiying | 来源:发表于2017-09-28 09:29 被阅读549次

    注:使用sdk版本为3.2.2

    1. model的主键如果是数字类型,必须使用封装类型

    greendao 查询方法 XXXDao的生成是使用greendao-generator中的dao.ftl为模板生成的

     @Override
        public boolean hasKey(${entity.className} entity) {
    <#if entity.pkProperty??>
    <#if entity.pkProperty.notNull>
            throw new UnsupportedOperationException("Unsupported for entities with a non-null key");
    <#else>
    <#if entity.protobuf>
            return entity.has${entity.pkProperty.propertyName?cap_first}();
    <#else>
            return entity.get${entity.pkProperty.propertyName?cap_first}() != null;
    </#if>
    </#if>
    <#else>
            // TODO 使用 notNull的判断会直接判断 xxx != null, 数字类型生成模板就是错误的
            return false;
    </#if>
        }
    
    2. AbstractDao.save() 使用范围
    • pk为自增状态下不设置 pk的保存
    • 当前model已存数据库,需要更新
    public void save(T entity) {
        if (hasKey(entity)) {
            update(entity);
        } else {
            insert(entity);
        }
    }
    
    3. AbstractDao的缓存机制

    AbstractDao除了使用方便外,还构建了自己的缓存机制

    public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
                daoConfigMap)
    //IdentityScopeType Session, None
    
    //DaoConfig
    @SuppressWarnings("rawtypes")
    public void initIdentityScope(IdentityScopeType type) {
        if (type == IdentityScopeType.None) {
                identityScope = null;
            } else if (type == IdentityScopeType.Session) {
                if (keyIsNumeric) {
                    identityScope = new IdentityScopeLong();
                } else {
                    identityScope = new IdentityScopeObject();
                }
            } else {
                throw new IllegalArgumentException("Unsupported type: " + type);
            }
        }
    
    //AbstractDao
    public T load(K key) {
            assertSinglePk();
            if (key == null) {
                return null;
            }
            if (identityScope != null) {
                T entity = identityScope.get(key);
                //获取缓存中entity
                if (entity != null) {
                    return entity;
                }
            }
            String sql = statements.getSelectByKey();
            String[] keyArray = new String[]{key.toString()};
            Cursor cursor = db.rawQuery(sql, keyArray);
            return loadUniqueAndCloseCursor(cursor);
        }
    
    /** Internal use only. Considers identity scope. */
        final protected T loadCurrent(Cursor cursor, int offset, boolean lock) {
            if (identityScopeLong != null) {
                if (offset != 0) {
                    // Occurs with deep loads (left outer joins)
                    if (cursor.isNull(pkOrdinal + offset)) {
                        return null;
                    }
                }
    
                long key = cursor.getLong(pkOrdinal + offset);
                T entity = lock ? identityScopeLong.get2(key) : identityScopeLong.get2NoLock(key);
                if (entity != null) {
                    return entity;
                } else {
                    entity = readEntity(cursor, offset);
                    attachEntity(entity);
                    if (lock) {
                        identityScopeLong.put2(key, entity);
                    } else {
                        identityScopeLong.put2NoLock(key, entity);
                    }
                    return entity;
                }
            } else if (identityScope != null) {
                K key = readKey(cursor, offset);
                if (offset != 0 && key == null) {
                    // Occurs with deep loads (left outer joins)
                    return null;
                }
                T entity = lock ? identityScope.get(key) : identityScope.getNoLock(key);
                if (entity != null) {
                    return entity;
                } else {
                    entity = readEntity(cursor, offset);
                    attachEntity(key, entity, lock);
                    return entity;
                }
            } else {
                // Check offset, assume a value !=0 indicating a potential outer join, so check PK
                if (offset != 0) {
                    K key = readKey(cursor, offset);
                    if (key == null) {
                        // Occurs with deep loads (left outer joins)
                        return null;
                    }
                }
                T entity = readEntity(cursor, offset);
                attachEntity(entity);
                return entity;
            }
        }
    //AbstractDao中只要调用这两个方法,就会把查询结果加入缓存中
    //如果同时对获取到的结果进行修改,缓存中的model就会相应变化
    //AbstractDao.queryRaw()不涉及缓存, queryBuilder方法会使用缓存数据
    
    4. 执行SQL语句无效
    5. Cursor的内存泄露

    GreenDao封装好了查询,cursor的生成与关闭都是在 AbstractDao中进行的,那么多线程操作时就可能会存在内存泄露的可能性。现在还没有好的解决方法

    相关文章

      网友评论

          本文标题:GreenDao遇到的一些坑

          本文链接:https://www.haomeiwen.com/subject/blqmextx.html