You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Realm OrderedRealmCollection从MongoDB取数据返回空列表求助

问题原因与解决方案

你的代码核心问题是没有连接MongoDB远程服务并同步数据,只是初始化了本地Realm,而本地Realm默认是空的,所以查询返回空列表。以下是具体错误点和修复步骤:

核心错误点

  • 未完成MongoDB用户认证:访问远程MongoDB数据必须先通过App Services完成用户登录(哪怕是匿名登录)。
  • 未配置Realm Sync:本地Realm没有和远程maindb.doctors集合建立同步关系,本地无数据。
  • 直接查询本地空Realm:当前查询的是本地未同步的Realm,自然返回空集合。

修复步骤

1. 修改Doctor模型类(确保注解正确)

添加@RealmClass注解标识为Realm同步模型类:

package com.example.hospital;

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

import org.bson.types.ObjectId;

@RealmClass
public class Doctor extends RealmObject {
    @PrimaryKey
    @Required
    private ObjectId _id;

    private String emp_id;
    private String name;
    private String specialisation;

    // Getters & Setters
    public ObjectId getId() { return _id; }
    public void setId(ObjectId _id) { this._id = _id; }

    public String getEmpId() { return emp_id; }
    public void setEmpId(String emp_id) { this.emp_id = emp_id; }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getSpecialisation() { return specialisation; }
    public void setSpecialisation(String specialisation) { this.specialisation = specialisation; }
}

2. 重构docselect类(添加认证与同步逻辑)

替换原有代码,实现匿名登录、同步Realm配置,并监听数据变化自动更新UI:

package com.example.hospital;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.example.hospital.ui.main.DoctorAdapter;

import io.realm.OrderedRealmCollection;
import io.realm.Realm;
import io.realm.mongodb.App;
import io.realm.mongodb.AppConfiguration;
import io.realm.mongodb.Credentials;
import io.realm.mongodb.sync.SyncConfiguration;

public class docselect extends AppCompatActivity {
    String Appid = "你的实际AppID"; // 替换为MongoDB App Services的真实AppID
    App app;
    Realm realm;
    DoctorAdapter adapter;
    RecyclerView recyclerView;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_docselect);

        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        // 初始化MongoDB Realm App
        app = new App(new AppConfiguration.Builder(Appid).build());

        // 匿名登录(需在App Services控制台开启匿名认证)
        app.loginAsync(Credentials.anonymous(), result -> {
            if (result.isSuccess()) {
                Log.d("DocSelect", "匿名登录成功");
                configureSyncRealm();
            } else {
                Log.e("DocSelect", "登录失败", result.getError());
                Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void configureSyncRealm() {
        // 构建同步配置,关联远程maindb.doctors集合
        SyncConfiguration syncConfig = new SyncConfiguration.Builder(app.currentUser(), "maindb.doctors")
                .schemaVersion(1)
                .migration(new MyRealmMigration())
                .build();

        // 异步打开同步Realm,避免阻塞主线程
        Realm.getInstanceAsync(syncConfig, new Realm.Callback() {
            @Override
            public void onSuccess(Realm realm) {
                docselect.this.realm = realm;
                Log.d("DocSelect", "同步Realm打开成功");
                setupRecyclerView(realm);
            }

            @Override
            public void onError(Throwable error) {
                Log.e("DocSelect", "打开同步Realm失败", error);
                Toast.makeText(docselect.this, "加载数据失败", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void setupRecyclerView(Realm realm) {
        // 异步查询同步Realm中的数据
        OrderedRealmCollection<Doctor> doctors = realm.where(Doctor.class).findAllAsync();
        
        // 监听数据变化,自动更新UI
        doctors.addChangeListener(collection -> {
            Log.d("DoctorAdapter", "数据更新,医生数量: " + collection.size());
            if (adapter == null) {
                adapter = new DoctorAdapter(collection);
                recyclerView.setAdapter(adapter);
            } else {
                adapter.notifyDataSetChanged();
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (realm != null) {
            realm.close();
        }
    }
}

3. MongoDB App Services控制台配置

  • 开启匿名认证:进入App Services -> Authentication -> Providers,启用Anonymous provider。
  • 配置Flexible Sync:进入App Services -> Sync,添加查询规则(测试阶段可设置{}允许同步所有maindb.doctors数据)。
  • 确认远程集合有数据:检查MongoDB Atlas中maindb.doctors集合是否存在实际数据。

额外建议

  • 优先使用findAllAsync()异步查询,避免阻塞主线程导致ANR。
  • 利用Realm的addChangeListener实现数据自动同步更新,无需手动调用notifyDataSetChanged()。
  • 测试时先排查远程集合数据、同步规则、用户认证是否正常,再检查客户端代码。

内容的提问来源于stack exchange,提问作者eren820

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:45:54