0

更新:

此时我无法创建任何新的基于 Realm 的对象。无论我是否清理、重建等,每一个都失败并出现相同的错误。为了测试这一点,我创建了一个新类“Sample”:

package com.reddragon.intouch.model;

import java.util.UUID;

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;

public class Sample extends RealmObject {
    @PrimaryKey
    private String id;
    private String sampleField;

    public Sample() {
        this(UUID.randomUUID().toString());
    }
    private Sample(String id) {
        this.id=id;
    }
    public String getId(){
        return id;
    }

    public String getSampleField() {
        return sampleField;
    }

    public void setSampleField(String sampleField) {
        this.sampleField = sampleField;
    }
}

在我的 MainActivity.java 中,我尝试创建一个新实例:

    try {
        MediaDataMgr.get().addSample(new Sample());
        Timber.d("Lifecycle: was able to add Sample");
    } catch (Exception e) {
        Timber.d("Got exception instantiating Sample: %s", e.getMessage());
    }

此方法使用与此项目中可以addSample()工作的两个类类似的方法:

public String addSample(Sample s) {
    boolean success = true;
    Sample sample;
    Realm realm;
    String retVal = null;
    boolean mainThread = Thread.currentThread().equals(Looper.getMainLooper().getThread());
    if (mainThread) {
        realm = mUIThreadRealm;
    } else {
        realm = Realm.getDefaultInstance();
    }
    try {
        realm.beginTransaction();
        sample = realm.createObject(Sample.class,s.getId()); //<--CRASH!!!!
        sample.setSampleField(s.getSampleField());
    } catch (Exception e ) {
        Timber.d( "Exception adding a Sample: %s", e.getMessage());
        success = false;
    } finally  {

        if ( success ) {
            realm.commitTransaction();
            retVal = s.getId();
        } else {
            realm.cancelTransaction();
        }
        if (!mainThread) {
            realm.close();
        }
    }
    return retVal;
}

我现在完全被这个项目困住了。

更新:

我在我的应用程序中完全注释了对“联系人”对象的所有引用,然后从我的项目中删除了 Contact.java。我做了一个完整的重建,然后运行它,一切正常。

然后我创建了一个新类 Contact.java 并输入了与以前相同的字段等,并在我的项目的其余部分中取消了对它的引用。我进行了重建并运行 - 并得到了同样的错误。

然后我将 Contact 类的名称重构为ContactSharingInfo,认为某处可能存在类名冲突。重建并再次运行 - 同样的错误,这次引用了新的类名。

原帖:

我正在使用 gradle 插件和注释处理器 5.9.1。我创建了一个新类(“Contact.java”),最初工作正常。然后我调整了类(删除了几个字段,添加了一个新字段),我开始收到这个错误。我已经在三星 S7 Edge (API 26) 以及几个模拟器上对此进行了测试。同样的问题。

我已经完成了各种清理、重建、无效缓存和重新启动等操作。没有帮助。我查看了错误#3819#4579,但其中没有任何帮助。我已禁用即时运行。没有帮助。

堆栈跟踪是:

realmSet$id:111, com_reddragon_intouch_model_ContactRealmProxy (io.realm)
<init>:30, Contact (com.reddragon.intouch.model)
<init>:26, Contact (com.reddragon.intouch.model)
<init>:84, com_reddragon_intouch_model_ContactRealmProxy (io.realm)
newInstance:96, DefaultRealmModuleMediator (io.realm)
createObjectInternal:1048, Realm (io.realm)
createObject:1024, Realm (io.realm)
addContact:877, MediaDataMgr (com.reddragon.intouch.model)

导致此问题的代码(我集中 Realm 访问的 MediaDataMgr 类中的 addContact() )是:

    public String addContact(Contact c, int status) {
        boolean success = true;
        Contact contact;
        Realm realm;
        String retVal = null;
        boolean mainThread = Thread.currentThread().equals(Looper.getMainLooper().getThread());
        if (mainThread) {
            realm = mUIThreadRealm;
        } else {
            realm = Realm.getDefaultInstance();
        }
        try {
            realm.beginTransaction();
            contact = realm.createObject(Contact.class,c.getId()); // <--CRASH HAPPENS HERE
            contact.setEmailAddress(c.getEmailAddress());
            contact.setDisplayName(c.getDisplayName());
            contact.setStatus(status);

        } catch (Exception e ) {
            Timber.d( "Exception adding a contact: %s", e.getMessage());
            success = false;
        } finally  {

                if ( success ) {
                    realm.commitTransaction();
                    retVal = c.getId();
            } else {
                realm.cancelTransaction();
            }
            if (!mainThread) {
                realm.close();
            }
        }
        return retVal;
    }

堆栈跟踪中引用的 Contact 类是:

public class Contact extends RealmObject implements CardListable {
    @PrimaryKey
    private String id;
    private String displayName;
    private String emailAddress;
    private String pathToProfilePic; // This will always be a URI, but we have to store it as a string and convert to URI at runtime.
    @Ignore
    private int status = STATUS_UNKNOWN;

    public Contact() {
        this(UUID.randomUUID().toString());
    }

    private Contact(String id) {
        this.id = id;
    }

    public String getId(){
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getPathToProfilePic() {
        return pathToProfilePic;
    }

    public void setPathToProfilePic(String pathToProfilePic) {
        this.pathToProfilePic = pathToProfilePic;
    }

    public String getFirstLineDesc() {
        return displayName;
    }

    public String getSecondLineDesc() {
        return emailAddress;
    }
}

在调试到 com_reddragon_intouch_model_ContactRealmProxy.java 类时,发现异常是因为public String realmSet$id()调用方法时变量 'proxyState' 为空:

    public void realmSet$id(String value) {
        if (proxyState.isUnderConstruction()) { //<-- CRASH HAPPENS HERE
            // default value of the primary key is always ignored.
            return;
        }

        proxyState.getRealm$realm().checkIfValid();
        throw new io.realm.exceptions.RealmException("Primary key field 'id' cannot be changed after object was created.");
    }

这让我相信 proxyState 的初始化realm$injectObjectContext()没有被调用。

这种创建新对象的相同方法在同一个项目中与其他两个类一起工作得很好,我验证了realm$injectObjectContext() IS在那里被调用。这是我的 Media.java 类(有效)的相同类型构造中的堆栈跟踪:

realm$injectObjectContext:105, com_reddragon_intouch_model_MediaRealmProxy (io.realm)
<init>:52, Media (com.reddragon.intouch.model)
<init>:49, Media (com.reddragon.intouch.model)
<init>:99, com_reddragon_intouch_model_MediaRealmProxy (io.realm)
newInstance:99, DefaultRealmModuleMediator (io.realm)
createObjectInternal:1048, Realm (io.realm)
createObject:1024, Realm (io.realm)
addMedia:267, MediaDataMgr (com.reddragon.intouch.model)

因此,如何为 Contact 类生成代码的方式必须与其他有效的代码不同 - 并且“某事”使 Realm 不调用该方法感到困惑。

该怎么办?

4

1 回答 1

0

解决方案:

就我而言,我是 Lint 重构的不知情的受害者。事实证明,我已经在我的类中运行了一些 Lint 进程,建议的更改之一是将某些构造函数更改为声明为私有的。显然,Realm 在构造函数中采用默认参数的模型类中不喜欢这样。因此,例如 Contact.java 类有这个构造函数:

public class Contact extends RealmObject implements CardListable {
    @PrimaryKey
    private String id;
    private String displayName;
    private String emailAddress;
    private String pathToProfilePic; // This will always be a URI, but we have to store it as a string and convert to URI at runtime.
    @Ignore
    private int status = STATUS_UNKNOWN;

    public Contact() {
        this(UUID.randomUUID().toString());
    }

    private Contact(String id) { //<--NOTE PRIVATE CONSTRUCTOR
        this.id = id;
    }

更改为:

public Contact() {
    this(UUID.randomUUID().toString());
}

public Contact(String id) { //<--NOTE THIS IS NOW PUBLIC
    this.id = id;
}

并进行清洁+重建解决了这个问题。

于 2019-03-07T18:14:14.667 回答