无法从领域对象检索字段值,调试器中的值为null

时间:2016-05-20 16:37:34

标签: android realm

似乎RealmProxy类隐藏了我的RealmObject值,但可以从代理类设置。

我可以看到,我的模型非常简单。

public class GroupRealm extends RealmObject {
    @PrimaryKey
    public String id;
    @Index
    public String name;
    public String imageUrl;
    public int order;

    public GroupRealm parent;
    public RealmList<GroupRealm> children;
    public RealmList<ContentRealm> contents;
}

这就是我设置值的方式(db是一个有效的Realm,一切都在提交正常的事务中):

GroupRealm gr = db.where(GroupRealm.class).equalTo("id",g.GroupID).findFirst();
        if(gr==null){
            gr = db.createObject(GroupRealm.class,g.GroupID);
        }
        gr.imageUrl = g.GlyphUrl;
        gr.name = g.Title;
        gr.order = g.OrderNum;

下面的图片是我查询db后面的内容。(相同的变量名称在代码中的位置不同)

RealmObject has values RealmProxyClass does not

在我的android.library中我的RealmObjects被定义为项目我有必要的插件。

apply plugin: 'com.android.library'
apply plugin: 'realm-android'

在项目级别我正在设置正确的依赖项:

dependencies {
    classpath 'com.android.tools.build:gradle:2.1.0'
    classpath "io.realm:realm-gradle-plugin:0.90.1"
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

我没有想法。如果我尝试访问任何内容,我会按预期检索GroupRealm,但通过代理类公开的所有公共属性都返回null!

4 个答案:

答案 0 :(得分:4)

文档中的相关常见问题解答:https://realm.io/docs/java/latest/#debugging

Realm使用Android Gradle Transform API。它可以在编译的类文件转换为dex文件之前对其进行操作 io.realm.transformer.RealmTransformer io.realm.transformer中的更多详细信息。 BytecodeModifier 类,可以在领域的github中找到。

RealmTransformer所做的是:

  • 用适当的Realm访问者替换对用户的RealmObjects字段的所有访问。

您还可以检查文件夹 app / build / intermediates / transforms / RealmTransformer /

中的结果类

setter示例:
你的代码行:

gr.imageUrl = g.GlyphUrl;

将替换为以下内容:

String var5 = g.GlyphUrl;
gr.realmSet$imageUrl(var5);

吸气剂示例:

String url = gr.imageUrl;

将替换为以下内容:

String url = gr.realmGet$imageUrl();

示例用例

  1. 您已创建课程 GroupRealm 。使用Transform API的领域生成 GroupRealmRealmProxy 。此代理类如下所示:

    public class GroupRealmRealmProxy extends GroupRealm implements RealmObjectProxy, GroupRealmRealmProxyInterface {
        private final GroupRealmRealmProxy.GroupRealmColumnInfo columnInfo;
        private final ProxyState proxyState;
        private RealmList<GroupRealm> childrenRealmList;
        private RealmList<ContentRealm> contentsRealmList;
        private static final List<String> FIELD_NAMES;
    
        GroupRealmRealmProxy(ColumnInfo columnInfo) {
            ...
        }
    
        public String realmGet$id() {
            this.proxyState.getRealm$realm().checkIfValid();
            return this.proxyState.getRow$realm().getString(this.columnInfo.idIndex);
        }
    
        public void realmSet$id(String value) {
            this.proxyState.getRealm$realm().checkIfValid();
            if(value == null) {
                this.proxyState.getRow$realm().setNull(this.columnInfo.idIndex);
            } else {
               this.proxyState.getRow$realm().setString(this.columnInfo.idIndex, value);
            }
        }
    
        public String realmGet$name() {
            this.proxyState.getRealm$realm().checkIfValid();
            return this.proxyState.getRow$realm().getString(this.columnInfo.nameIndex);
        }
    
        public void realmSet$name(String value) {
            this.proxyState.getRealm$realm().checkIfValid();
            if(value == null) {
                this.proxyState.getRow$realm().setNull(this.columnInfo.nameIndex);
            } else {
                this.proxyState.getRow$realm().setString(this.columnInfo.nameIndex, value);
            }
         }
    
        ...
    }
    

    您可以观察到 realmSet $ name realmGet $ name 方法无权访问GroupRealm类中声明的字段 name 。他们使用 proxyState

  2. 现在,让我们回到GroupRealm的用法。调试代码时:

    GroupRealm gr = db.where(GroupRealm.class).equalTo("id",g.GroupID).findFirst();
    if(gr==null){
        gr = db.createObject(GroupRealm.class,g.GroupID);
    }
    gr.imageUrl = g.GlyphUrl;
    gr.name = g.Title;
    gr.order = g.OrderNum;
    

    实际上它的反编译版本看起来像这样:

    GroupRealm gr = (GroupRealm)realm.where(GroupRealm.class).equalTo("id", g.GroupId).findFirst();
    if(gr == null) {
        gr = (GroupRealm)realm.createObject(GroupRealm.class, g.GroupId);
    }
    
    String var7 = g.GlyphUrl;
    gr.realmSet$imageUrl(var7);
    var7 = g.Title;
    gr.realmSet$name(var7);
    int var8 = g.OrderNum;
    gr.realmSet$order(var8);
    

    首先, gr GroupRealmRealmProxy 类的实例。如您所见,gr.name的设置被 gr.realmSet $ name(var7)替换。这意味着永远不会使用 GroupRealm 字段名称。情况类似于 realmGet $

  3. 在调试时,您会看到您的源代码版本,但实际上您正在使用带有注入方法 realmSet $ realmGet $ 的修改版本。

答案 1 :(得分:1)

字段 为空。您可以通过替换所有字段访问的本机方法来访问属性。以前(在0.88.0之前),它曾用于创建一个动态代理,它会覆盖您的getter和setter以使用其本机代理实现。

这些字段没有值。但正如您所看到的,Realm对象的值很好:它在toString()值中表示如此。

答案 2 :(得分:0)

没有什么可做的。由于Realm在做“聪明”的事情,因此完全阻止了调试器执行应做的事情。您将不得不依赖大量Log.d语句。

对不起。这就是事实。

答案 3 :(得分:0)

如果您直接使用从您的领域检索的RealmObject,那么上面的答案就可以了。使用Managed RealmObject(对象“直接”与您的Realm连接,因此您在Realm内的对象的“ Real Instance”只能在RealmTransaction内进行修改,并且所做的更改将立即影响所有其他Managed RealmInstance),因此您看不到它们的值由于存在代理,因此在调试器内部。

无论如何,您都可以通过使用NO MANAGED对象来解决此问题,因此可以从领域中复制RealmObject:

MyRealmObject obj = getRealmObjectFromRealm();
if(obj != null){
    obj = mRealm.copyFromRealm(obj);
}

这样,您将在调试器中看到领域对象的所有属性。 显然,如果需要在代码内使用托管领域对象,则在调试时,需要通过创建另一个“ MyRealmObject”实例(它是另一个“ MyRealmObject”的领域的副本)来更改代码。

这样,您将看到调试器中的所有对象属性(:

希望这会有所帮助, 问候和编码不错!

:D