web-dev-qa-db-ja.com

レルムオブジェクトからフィールド値を取得できません。デバッガーでは値がnullです。

RealmObjectの値がRealmProxyクラスによって隠されているようですが、proxyclassから設定できます。

ご覧のとおり、私のモデルは非常に単純です。

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は有効なレルムであり、すべてが正常にコミットするトランザクションにあります):

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

RealmObjectsが定義されているプロジェクトであるAndroid.libraryには、必要なプラグインがあります。

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を返します。

13
Theyouthis

関連FAQドキュメント内: https://realm.io/docs/Java/latest/#debugging


RealmはAndroid Gradle Transform APIを使用します。これにより、コンパイルされたクラスファイルをdexファイルに変換する前に操作することができます。
io.realm.transformer.RealmTransformerおよびio.realm.transformer内の詳細。レルムのgithubにあるBytecodeModifierクラス。

RealmTransformerが行うことは、とりわけ次のとおりです。

  • ユーザーのRealmObjectsのフィールドへのすべてのアクセスを適切なRealmアクセサーに置き換えます。

フォルダ内の結果クラスを確認することもできますapp/build/intermediates/transforms/RealmTransformer /

セッターの例:
コードの行:

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がないことを確認できます。 tクラス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);
    

    まず、grGroupRealmRealmProxyクラスのインスタンスです。ご覧のとおり、gr.nameの設定はgr.realmSet $ name(var7)に置き換えられています。これは、GroupRealmのフィールドnameが使用されないことを意味します。 realmGet $の場合も状況は似ています。

デバッグ中にソースコードのバージョンが表示されますが、実際には、メソッドrealmSet $およびが挿入された変更バージョンを使用しています。 )realmGet $

6
PiKos

フィールドare null。すべてのフィールドアクセスを置き換えるネイティブメソッドを介してプロパティにアクセスします。以前(0.88.0より前)は、ネイティブプロキシ実装を使用するためにゲッターとセッターをオーバーライドする動的プロキシを作成するために使用されていました。

フィールドには値がありません。しかし、ご覧のとおり、Realmオブジェクトの値は問題ありません。toString()値にそのように記載されています。

2
EpicPandaForce

これについては何もする必要はありません。 Realmが実行している「巧妙な」ことにより、デバッガーは想定どおりに実行できなくなります。多くのLog.dステートメントに依存する必要があります。

申し訳ありません。それが現実です。

1
Leonhard Printz

レルムから取得したRealmObjectを直接使用する場合は、上記の回答で問題ありません。 Managed RealmObject(Realmに「直接」接続されているオブジェクト、つまりRealmTransaction内でのみ変更でき、変更が他のすべてのManaged RealmInstanceに即座に影響するRealm内のオブジェクトの「RealInstance」)では、それらの値を確認できません。プロキシのため、デバッガーの内部。

とにかく、NO MANAGEDオブジェクトを使用してこれを回避できるので、レルムからRealmObjectをコピーします。

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

このようにして、デバッガー内のレルムオブジェクトのすべてのプロパティを確認できます。明らかに、コード内でマネージドレルムオブジェクトを使用する必要がある場合は、デバッグ時に、他の「MyRealmObject」のレルムからのコピーである別の「MyRealmObject」インスタンスを作成してコードを変更する必要があります。

このようにして、デバッガー内のすべてのオブジェクトのプロパティが表示されます(:

これがお役に立てば幸いです、ご挨拶&素敵なコーディングを!

:D

0
Z3R0