使用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
相关产品推荐
相关产品推荐

