查询包含在其他对象上的领域数据

Query realm data contained on other object

这个问题是后续问题:

由于我们使用的 API 返回的数据,在领域数据库上进行实际查询有点不可能。相反,我将订购的数据包装在 RealmList 中并向其添加 @PrimaryKey public String id;

所以我们的领域数据看起来像:

public class ListPhoto extends RealmObject {
   @PrimaryKey public String id;
   public RealmList<Photo> list; // Photo contains String/int/boolean
}

只需使用 API 端点作为 id.

即可轻松写入和读取 Realm DB

所以一个典型的查询看起来像:

realm.where(ListPhoto.class).equalTo("id", id).findFirstAsync();

这会对数据造成 listening/subscribing 的轻微开销,因为现在我需要检查 listUser.isLoaded() 使用 ListUseraddChangeListener/removeChangeListenerListUser.list 作为实际我适配器上的数据。

所以我的问题是:

有什么方法可以查询此领域以接收 RealmResults<Photo>。这样我就可以轻松地在 RealmRecyclerViewAdapter 中使用这些数据并直接在其上使用监听器。

编辑: 进一步澄清,我想要类似下面的东西(我知道这不能编译,它只是我想要实现的伪代码).

realm
 .where(ListPhoto.class)
      .equalTo("id", id)
      .findFirstAsync()  // get a results of that photo list
 .where(Photo.class)
      .getField("list")
      .findAllAsync(); // get the field "list" into a `RealmResults<Photo>`

编辑最终代码: 考虑到 ATM 不可能直接在查询时执行此操作,我的最终解决方案是简单地使用一个适配器来检查数据并在需要时订阅。代码如下:

public abstract class RealmAdapter
                     <T extends RealmModel, 
                      VH extends RecyclerView.ViewHolder> 
            extends RealmRecyclerViewAdapter<T, VH>
            implements RealmChangeListener<RealmModel> {

   public RealmAdapter(Context context, OrderedRealmCollection data, RealmObject realmObject) {
      super(context, data, true);
      if (data == null) {
         realmObject.addChangeListener(this);
      }
   }

   @Override public void onChange(RealmModel element) {

      RealmList list = null;
      try {
         // accessing the `getter` from the generated class
         // because it can be list of Photo, User, Album, Comment, etc
         // but the field name will always be `list` so the generated will always be realmGet$list
         list = (RealmList) element.getClass().getMethod("realmGet$list").invoke(element);
      } catch (Exception e) {
         e.printStackTrace();
      }

      if (list != null) {
         ((RealmObject) element).removeChangeListener(this);
         updateData(list);
      }
   }
}

首先查询 ListPhoto,因为它是异步的,所以您必须为结果注册一个侦听器。然后在该侦听器中,您可以查询结果以获得 RealmResult。

像这样

final ListPhoto listPhoto = realm.where(ListPhoto.class).equalTo("id", id).findFirstAsync();
listPhoto.addChangeListener(new RealmChangeListener<RealmModel>() {
    @Override
    public void onChange(RealmModel element) {
        RealmResults<Photo> photos = listPhoto.getList().where().findAll();
        // do stuff with your photo results here.


        // unregister the listener.
        listPhoto.removeChangeListeners();
    }
});

请注意,您实际上可以查询 RealmList。这就是为什么我们可以调用 listPhoto.getList().where()where() 仅表示 "return all".

我无法测试它,因为我没有您的代码。您可能需要将 element 转换为 ((ListPhoto) element)

我知道你说过你不考虑使用同步 API 的选项,但我仍然认为值得注意的是你的问题会像这样解决:

RealmResults<Photo> results = realm.where(ListPhoto.class).equalTo("id", id).findFirst()
                           .getList().where().findAll();

编辑: 为了提供完整的信息,我引用了 docs

findFirstAsync

public E findFirstAsync()

Similar to findFirst() but runs asynchronously on a worker thread This method is only available from a Looper thread.

Returns: immediately an empty RealmObject.

Trying to access any field on the returned object before it is loaded will throw an IllegalStateException.

Use RealmObject.isLoaded() to check if the object is fully loaded

or register a listener RealmObject.addChangeListener(io.realm.RealmChangeListener<E>) to be notified when the query completes.

If no RealmObject was found after the query completed, the returned RealmObject will have RealmObject.isLoaded() set to true and RealmObject.isValid() set to false.

从技术上讲是的,您需要执行以下操作:

private OrderedRealmCollection<Photo> photos = null;
//...

final ListPhoto listPhoto = realm.where(ListPhoto.class).equalTo("id", id).findFirstAsync();
listPhoto.addChangeListener(new RealmChangeListener<ListPhoto>() {
    @Override
    public void onChange(ListPhoto element) {
        if(element.isValid()) {
            realmRecyclerViewAdapter.updateData(element.list);
        }
        listPhoto.removeChangeListeners();
    }
}