Правильное обновление RealmModel после onClick без блокировки пользовательского интерфейса в Android

У меня есть RecyclerView, который отображает элементы из базы данных Realm. Для этого я реализовал RealmRecyclerViewAdapter на основе адаптеров realm-android, который получает OrderedRealmCollection передано. Для этого я загружаю данные с помощью findAllAsync()

realm.where(Entry.class).findAllAsync()

Когда пользователь прокручивает список, у него есть возможность добавить некоторые записи в избранное, что я реализовал с помощью обычного OnClickListener на кнопке «Избранное».

Теперь я хотел бы обновить «любимое» логическое значение записи всякий раз, когда пользователь нажимает кнопку. После нажатия пользователем на кнопке отображается небольшая анимация.

Для этого я попробовал следующее, что, к сожалению, дает неправильное исключение потока:

realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        entry.setLiked(!entry.isLiked());
    }
});

В качестве альтернативы я попробовал это с обычным executeTransaction, который будет работать, но анимация не будет отображаться.

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        entry.setLiked(!entry.isLiked());
    }
});

В качестве интересного дополнения это дает следующий журнал:

Следует избегать смешивания асинхронных запросов с локальными операциями записи. Realm преобразует любые асинхронные запросы в синхронные, чтобы оставаться согласованными. Вместо этого используйте асинхронную запись.

Есть ли возможность полностью асинхронно обновить элемент без задержки или предотвращения отображения анимации?


person mikepenz    schedule 11.08.2016    source источник


Ответы (2)


RealmRecyclerViewAdapter вызывает adapter.notifyDataSetChanged() при автоматическом обновлении Realm, поэтому анимация макета вызываться не будет.

Что касается фактического внесения изменений,

public class EntryViewHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.entry_favorite)
    Button favButton;

    public EntryViewHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);
    }

    public void bind(Entry entry) {
        final long entryId = entry.getId();
        favButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 realm.executeTransactionAsync(new Realm.Transaction() {
                     @Override
                     public void execute(Realm realm) {
                         Entry entry = realm.where(Entry.class)
                                            .equalTo("id", id)
                                            .findFirst();
                         if(entry != null) {
                             entry.deleteFromRealm();
                         }
                     }
                 });
             }
        });
    }
}
person EpicPandaForce    schedule 13.08.2016
comment
вы правы, это было просто связано с adapter.notifyDataSetChanged(), предотвращающим приложение. полностью упустил из виду, что это также будет срабатывать каждый раз, когда я обновляюсь. спасибо - person mikepenz; 15.08.2016

Выполните это в фоновом потоке. Я рекомендую использовать классическую анимацию Thread.class .Start вне нового потока и отклонять его с помощью обратного вызова в потоке пользовательского интерфейса.

Realm realm = Realm.getInstance(..);
realm.beginTransaction();
YourClass yourClassInstance = realm.where(YourClass.class)
        .equalTo(..)
        .findFirst();
if(yourClassInstance != null){
   yourClassInstance.setLiked(!yourClassInstance.getLiked());
}else{
   yourClassInstance = realm.createObject(YourClass.class);
   yourClassInstance.setLiked(whateverYouWant);
}
realm.commitTransaction();
person Dragos-Daniel Dit    schedule 11.08.2016