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

时间:2016-07-06 09:08:00

标签: android realm realm-list

此问题是来自Organize Android Realm data in lists

的后续问题

由于我们使用的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);
      }
   }
}

2 个答案:

答案 0 :(得分: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()的原因。 where()只是意味着“全部归还”。

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

答案 1 :(得分:1)

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

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

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

  

findFirstAsync

     

public E findFirstAsync()

     

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

     

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

     

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

     

使用RealmObject.isLoaded()检查对象是否已满载

     

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

     

如果之后没有找到RealmObject   查询完成后,返回的RealmObject将具有   RealmObject.isLoaded()设置为true,RealmObject.isValid()设置为   假的。

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

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();
    }
}