Realm的findFirst()方法返回null。

8

我搜索过FindFirst返回null类似的问题,但没有人回答。因为我觉得我可能做错了什么,让我用更多的细节来解释我的问题。

我正在开发一个应用程序,要求用户首先登录,然后让用户使用该应用程序。

我的User类如下:

public class User extends RealmObject {

    @PrimaryKey
    @SerializedName("uid")
    String id;
    @SerializedName("ufname")
    String firstName;
    @SerializedName("ulname")
    String lastName;
    String avatar;
    int sessions;
    int invites;
    String nextSessionTime;
    String nextSessionTitle;
    @SerializedName("lastlogin")
    String lastLogin;
    String token;

    @Override
    public String toString() {
        return new GsonBuilder().create().toJson(this, User.class);
    }

    // other setters and getters
}

成功登录后,我会将用户对象存储在 Realm 数据库中的 SigninActivity 类中:

@Override
public void onSignInResponse(final GeneralResponse response) {

    if (response == null) {
        Timber.e("response is null");
        return;
    }
    Timber.d(response.toString());

    if (response.isSuccess()) {
        // Store user's info including Token
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealmOrUpdate(response.getUser());
            }
        });

        // Goto main screen
        MainVideoActivity.startActivity(this);
        this.finish();

    } else {
        String errorMessage = response.getErrorMessages();
        super.displayMessage(errorMessage);
    }
}

一旦登录成功,应用程序将用户重定向到MainVideoActivity。我想通过以下代码在realm中查找用户,但是我得到了null

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main_video);

    // Create the Realm instance
    realm = Realm.getDefaultInstance();
    User user = realm.where(User.class).findFirst();
//        RealmResults<User> user = realm.where(User.class).findAll();
    Timber.d(user.toString());
}

user 在两种方法中都是 null

enter image description here

然而,我可以在数据库中看到我的非null用户。

enter image description here

我正在使用 classpath "io.realm:realm-gradle-plugin:2.0.2"


1
如果你在谈论调试窗口中的空值——那是正常的。请参见 https://realm.io/docs/java/latest/#android-studio-debugging - beeender
我有点困惑。从你的截图中,我可以看到用户已经被找到,session=0, invites=0与Realm浏览器中的值相匹配。我认为在第47行用户不是null? - beeender
@beeender 这些是默认值。正如您在调试器中看到的那样,idfirstNamelastName都是null,而在 Dev 工具截图中它们不是。 - Hesam
@Hesam 那不是 null,那是一个 RealmProxy。toString() 方法会告诉你它是什么。 - EpicPandaForce
@EpicPandaForce,我的问题是如何从RelamDB中获取我的User对象,这个返回的对象没有firstName、lastName和Token。 - Hesam
显示剩余5条评论
4个回答

9
这里有两个问题:
  1. 在调试窗口中出现了 null 值。这是使用 Realm 和调试器时已知的限制。由于 Realm 生成了代理类来访问值,在调试器中检查 RealmObject 的字段不会通过代理类。更多详细信息请参见此处

  2. toString() 方法中没有打印出具有 null 值的字段。如果在 RealmObject 中未定义 toString() 方法,则 Realm 注解处理器将生成一个 toString() 方法。我认为这里的问题是 User.toString() 忽略了 null 值。请尝试删除 User 类中的 toString() 方法。


感谢提供的详细信息。我已经删除了 toString(),现在 Timber.d(user.toString()); 打印出了一些结果。然而,我还发现了其他问题。真正的问题是 User 类中 toString() 方法中的 GsonBuilder()。我将其删除并替换为以下内容,然后得到了一个漂亮的打印结果。@Override public String toString() { return new StringBuilder().append("User{") .append("id='").append(id).append('\'') .append(", firstName='").append(firstName).append('\'') ... .toString(); } - Hesam

1
请替换


    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm.copyToRealmOrUpdate(response.getUser());
        }
    });

    // Goto main screen
    MainVideoActivity.startActivity(this);
    this.finish();

使用

    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm.copyToRealmOrUpdate(response.getUser());
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            // Goto main screen
            MainVideoActivity.startActivity(this);
            finish();
        }
    });

谢谢,你的方法明显比我的好。我会根据它更新我的代码。 - Hesam

1
根据 Realm 文档 Realm,你可以尝试在查询中添加 isNotNull(),如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main_video);

    // Create the Realm instance
    realm = Realm.getDefaultInstance();
    User user = realm.where(User.class).isNotNull("id").findFirst(); //add in this line isNotNull()
    //RealmResults<User> user = realm.where(User.class).findAll();
    Timber.d(user.toString());
}

我还没有测试过,但它应该可以工作。


谢谢帮忙,我将其更改为.isNotNull("id"),因为isNotNull()需要一个参数。然而,我得到了相同的结果并且我得到了null :( - Hesam
你可以尝试使用.findAll()并调试结果,如果你看不到任何东西,那么问题可能出在获取Realm实例上,你能否发布.findAll()的调试结果? - rockar06
我按照那种方式做了,但是得到了相同的结果。 - Hesam

-1

解决这个问题的一种方法是创建对象的非托管副本。

替换为:

User user = realm.where(User.class).findFirst();

使用

User managed_user = realm.where(User.class).findFirst();
  if(user!=null){
  User unmanaged_user = realm.copyFromRealm(managed_user)
}

返回未托管用户。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接