Запросить данные области, содержащиеся в другом объекте

1

Этот вопрос представляет собой следующий вопрос: Организуйте данные Android Realm в списках

Из-за данных, возвращаемых API, которые мы используем, немного невозможно сделать фактический запрос в базе данных области. Вместо этого я обертываю упорядоченные данные в RealmList и добавляю к нему @PrimaryKey public String id;.

Итак, наши данные в области данных выглядят следующим образом:

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

который упрощает запись и чтение из базы данных Realm, просто используя конечную точку API как id.

Таким образом, типичный запрос выглядит так:

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

Это создает незначительные накладные расходы listening/subscribing для данных, потому что теперь мне нужно проверить listUser.isLoaded() на использование ListUser на addChangeListener/removeChangeListener и ListUser.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>`

изменить окончательный код:, учитывая, что банкомат не может делать это непосредственно по запросам, моим окончательным решением было просто иметь адаптер, который проверяет данные и подписывается при необходимости. Код ниже:

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);
      }
   }
}
  • 0
    Есть ли способ, которым я могу запросить эту область, что вы хотите запросить точно? Результат realm.where(ListPhoto.class).equalTo("id", id).findFirstAsync(); ?
  • 0
    @TimCastelijns да. Я хотел бы получить RealmResults<Photo> (или даже непосредственно RealmList ), который будет соответствовать RealmList<Photo> внутри ListPhoto . Я знаю, что могу сделать это синхронным звонком. Но я действительно лучше использую async.
Показать ещё 7 комментариев
Теги:
realm

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(). where() просто означает "вернуть все".

Я не могу проверить это, потому что у меня нет вашего кода. Вам может потребоваться отбросить element с помощью ((ListPhoto) element).

  • 0
    спасибо Тим. Я боялся, что это был единственный ответ. Например, я не могу сгенерировать RealmResult (или List) непосредственно во время onCreate и должен ждать обратных вызовов.
  • 0
    @Budius, если вы используете асинхронные запросы, да, тогда вам придется ждать обратного вызова :-)
Показать ещё 3 комментария
1

Я знаю, что вы сказали, что не рассматриваете возможность использования синхронного API, но я все же считаю, что стоит отметить, что ваша проблема будет решена так:

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

EDIT: Чтобы быть полностью информативным, я цитирую 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();
    }
}
  • 0
    realm.where(ListPhoto.class).equalTo("id", id).findFirst().getList() вы объяснить, как это будет отличаться от прямого использования списка следующим образом: realm.where(ListPhoto.class).equalTo("id", id).findFirst().getList() Я имею в виду, если список уже существует Мне не нужен второй запрос, я могу напрямую использовать RealmList<Photo> . Нет?
  • 0
    Ну, технически да, так как я думаю 0.89.0 и введение интерфейса OrderedRealmCollection<T> , но вы сказали, что хотите RealmResults<Photo> , и это преобразует список в результаты. Но это просто делает ваш list .where().findAll() как view , на самом деле ничего не стоит делать .where().findAll() .
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню