1

这个问题是一个后续问题:Organize Android Realm data in lists

由于我们使用的 API 返回的数据,稍微不可能对领域数据库进行实际查询。相反,我将订购的数据包装在 a 中RealmList并添加 a @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.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);
      }
   }
}
4

2 回答 2

1

首先您查询 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(). just的where()意思是“归还所有”。

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

于 2016-07-06T09:30:31.137 回答
1

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

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

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

findFirstAsync

公共 E findFirstAsync()

与 findFirst() 类似,但在工作线程上异步运行此方法仅在 Looper 线程中可用。

返回:立即是一个空的 RealmObject。

在加载之前尝试访问返回对象上的任何字段将引发 IllegalStateException。

使用 RealmObject.isLoaded() 检查对象是否已完全加载

或注册一个侦听RealmObject.addChangeListener(io.realm.RealmChangeListener<E>)器以在查询完成时收到通知。

如果查询完成后没有找到 RealmObject,则返回的 RealmObject 将 RealmObject.isLoaded() 设置为 true,RealmObject.isValid() 设置为 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();
    }
}
于 2016-07-06T10:47:03.923 回答