Intereting Posts
CSS "float: right" эквивалент свойства в LinearLayout на android? NullPointerException на findViewById () в android Как изменить цвет кнопки в Android при нажатии? Android: как подождать AsyncTask для завершения в MainThread? Android – установить максимальную длину сообщений logcat В Android, можно ли использовать изображение из активов в макете xml? Как сканировать штрих-код с помощью телефонного разговора Запустить приложение для Android, когда ссылка используется в SMS Почему функция setVisibility не работает после просмотра анимированного представления? Сколько общих настроек слишком много? Изменение режима местоположения на высокую точность Программно для Android ПРОГРАММА ANDROID ELM327 / OBD2 BitmapFactory.decodeResource и доступные * папки Android webview, запускайте действие ACTION_VIEW, когда URL-адрес не может обрабатываться webview Перезапуск Android-приложения Phonegap вместо возобновления, хотя он не был убит операционной системой

Лучшие практики использования области с видом ресайклера?

У вас, ребята, есть какие-либо рекомендации по использованию сферы с помощью recyclerview? Я знаю, что это общий вопрос, но я ничего не нашел в Интернете. Например, я сталкиваюсь с множеством проблем, пытающихся реализовать простое изменение цвета в строке. Например, рассмотрим это типичное использование:

public class User extends RealmObject { @PrimaryKey String name; boolean isSelected; ... constructor, getter and setters } public class UserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private RealmResults<User> users; public UserAdapter(RealmResults<User> users) { this.users = users; } ... public void markAsSelected(int position){ // get the old selected user and deselect it notifyItemChanged(? how do i get the position given my User has no index ?); // mark as selected the new user at position } 

Я столкнулся с множеством проблем, так как не мог найти ничего в Интернете. Я знаю, это потому, что я не знаю, как правильно использовать сферу. Но найти правильный путь – это борьба сама по себе. Я прочитал всю их документацию, но безрезультатно.

EDIT: Поскольку меня попросили -> Вместо того, чтобы сказать «у меня есть ряд проблем с [этим]», опишите свои проблемы, и мы постараемся представить идеи и ответы на ваши непонимания.

Поэтому моя проблема проста:

У меня есть RealmUser:

 public class RealmUser extends RealmObject { @PrimaryKey private String key; private String name; private boolean isSelected; private boolean editMode; private RealmList<RealmItemList> lists; public RealmUser() {} public RealmUser(String name, RealmList<RealmItemList> lists, boolean isSelected , boolean editMode) { this.key = UUID.randomUUID().toString(); this.name = name; this.isSelected = isSelected; this.editMode = editMode; if (lists ==null){ this.lists = new RealmList<RealmItemList>(); }else{ this.lists = lists; } } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isSelected() { return isSelected; } public void setSelected(boolean isSelected) { this.isSelected = isSelected; } public boolean isEditMode() { return editMode; } public void setEditMode(boolean editMode) { this.editMode = editMode; } public RealmList<RealmItemList> getLists() { return lists; } public void setLists(RealmList<RealmItemList> lists) { this.lists = lists; } } 

Который я ввел в массив RealmResults, используя:

 RealmResults users = realm.where(RealmUser.class).findAll(); 

Я передаю свой пользовательский массив своему пользовательскому адаптеру:

 public class UserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private RealmResults<RealmUser> users; public UserAdapter(RealmResults<RealmUser> users) { this.users = users; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); if(viewType == 1){ View v = inflater.inflate(R.layout.detail_user, parent, false); return new UserHolder(v); }else if(viewType == 2){ View v = inflater.inflate(R.layout.edit_user, parent, false); return new editUserHolder(v); }else { return null; } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { RealmUser user = users.get(position); String userName = user.getName(); boolean isSelected = user.isSelected(); if (holder instanceof UserHolder ){ UserHolder uHolder = (UserHolder) holder; uHolder.userText.setText(userName); if (isSelected){ uHolder.userContainer.setBackgroundColor(Color.parseColor("#607D8B")); } }else if(holder instanceof editUserHolder){ editUserHolder eUserHolder = (editUserHolder) holder; eUserHolder.userEditContainer.setBackgroundColor(Color.parseColor("#eeeeee")); } } @Override public int getItemViewType(int position) { RealmUser user = users.get(position); if (user.isEditMode()){ return 2; }else { return 1; } } @Override public int getItemCount() { return users.size(); } public void markAsSelected(int position, DrawerLayout mDrawerLayout , Toolbar toolbar, Realm realm){ // Here is my problem : How do I get the already selected user asuming there is one in my db and notify the UI that I changed that item. } 

У этого есть пользовательский кликер Listener: он получает элемент recyclerview, который был нажат, используя:

 public class UserClickListener implements RecyclerView.OnItemTouchListener{ public static interface OnItemClickListener{ public void onItemClick(View v, int position); } private OnItemClickListener mListener; private GestureDetector mGestureDetector; public UserClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { View childView = recyclerView.findChildViewUnder(e.getX(), e.getY()); if(childView != null && mListener != null) { mListener.onItemClick(childView, recyclerView.getChildPosition(childView)); return true; } return false; } }); } @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { View childView = view.findChildViewUnder(e.getX(), e.getY()); if(childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildPosition(childView)); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } } 

Что я добавляю к моему recyclerView с addOnItemTouchListener:

 mListRecycler.addOnItemTouchListener(new UserClickListener(getActivity(), mListRecycler, new UserClickListener.OnItemClickListener(){ @Override public void onItemClick(View view, int position) { UserAdapter myadapter = (UserAdapter) mListRecycler.getAdapter(); myadapter.markAsSelected(position, mDrawerLayout , mToolbar, realm); } })); 

Solutions Collecting From Web of "Лучшие практики использования области с видом ресайклера?"

Для последних версий вы должны использовать RealmRecyclerViewAdapter в репозитории realm-android-adapters.


СТАРЫЙ ОТВЕТ ДЛЯ СТАРЫХ ВЕРСИЙ:

Я сделал этот RealmRecyclerViewAdapter на основе реализации RealmBaseAdapter .

Это для v0.89.0 И ВЫШЕ

 public abstract class RealmRecyclerViewAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { //put this in `io.realm` protected LayoutInflater inflater; protected OrderedRealmCollection<T> adapterData; protected Context context; private final RealmChangeListener listener; public RealmRecyclerViewAdapter(Context context, OrderedRealmCollection<T> data) { if (context == null) { throw new IllegalArgumentException("Context cannot be null"); } this.context = context; this.adapterData = data; this.inflater = LayoutInflater.from(context); this.listener = new RealmChangeListener<RealmResults<T>>() { @Override public void onChange(RealmResults<T> results) { notifyDataSetChanged(); } }; if (data != null) { addListener(data); } } private void addListener(OrderedRealmCollection<T> data) { if (data instanceof RealmResults) { RealmResults realmResults = (RealmResults) data; realmResults.addChangeListener(listener); } else if (data instanceof RealmList) { RealmList realmList = (RealmList) data; realmList.realm.handlerController.addChangeListenerAsWeakReference(listener); } else { throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); } } private void removeListener(OrderedRealmCollection<T> data) { if (data instanceof RealmResults) { RealmResults realmResults = (RealmResults) data; realmResults.removeChangeListener(listener); } else if (data instanceof RealmList) { RealmList realmList = (RealmList) data; realmList.realm.handlerController.removeWeakChangeListener(listener); } else { throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); } } /** * Returns how many items are in the data set. * * @return the number of items. */ @Override public int getItemCount() { if (adapterData == null) { return 0; } return adapterData.size(); } /** * Get the data item associated with the specified position in the data set. * * @param position Position of the item whose data we want within the adapter's * data set. * @return The data at the specified position. */ public T getItem(int position) { if (adapterData == null) { return null; } return adapterData.get(position); } /** * Get the row id associated with the specified position in the list. Note that item IDs are not stable so you * cannot rely on the item ID being the same after {@link #notifyDataSetChanged()} or * {@link #updateData(OrderedRealmCollection)} has been called. * * @param position The position of the item within the adapter's data set whose row id we want. * @return The id of the item at the specified position. */ @Override public long getItemId(int position) { // TODO: find better solution once we have unique IDs return position; } /** * Updates the data associated with the Adapter. * * Note that RealmResults and RealmLists are "live" views, so they will automatically be updated to reflect the * latest changes. This will also trigger {@code notifyDataSetChanged()} to be called on the adapter. * * This method is therefore only useful if you want to display data based on a new query without replacing the * adapter. * * @param data the new {@link OrderedRealmCollection} to display. */ public void updateData(OrderedRealmCollection<T> data) { if (listener != null) { if (adapterData != null) { removeListener(adapterData); } if (data != null) { addListener(data); } } this.adapterData = data; notifyDataSetChanged(); } } слушателя public abstract class RealmRecyclerViewAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { //put this in `io.realm` protected LayoutInflater inflater; protected OrderedRealmCollection<T> adapterData; protected Context context; private final RealmChangeListener listener; public RealmRecyclerViewAdapter(Context context, OrderedRealmCollection<T> data) { if (context == null) { throw new IllegalArgumentException("Context cannot be null"); } this.context = context; this.adapterData = data; this.inflater = LayoutInflater.from(context); this.listener = new RealmChangeListener<RealmResults<T>>() { @Override public void onChange(RealmResults<T> results) { notifyDataSetChanged(); } }; if (data != null) { addListener(data); } } private void addListener(OrderedRealmCollection<T> data) { if (data instanceof RealmResults) { RealmResults realmResults = (RealmResults) data; realmResults.addChangeListener(listener); } else if (data instanceof RealmList) { RealmList realmList = (RealmList) data; realmList.realm.handlerController.addChangeListenerAsWeakReference(listener); } else { throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); } } private void removeListener(OrderedRealmCollection<T> data) { if (data instanceof RealmResults) { RealmResults realmResults = (RealmResults) data; realmResults.removeChangeListener(listener); } else if (data instanceof RealmList) { RealmList realmList = (RealmList) data; realmList.realm.handlerController.removeWeakChangeListener(listener); } else { throw new IllegalArgumentException("RealmCollection not supported: " + data.getClass()); } } /** * Returns how many items are in the data set. * * @return the number of items. */ @Override public int getItemCount() { if (adapterData == null) { return 0; } return adapterData.size(); } /** * Get the data item associated with the specified position in the data set. * * @param position Position of the item whose data we want within the adapter's * data set. * @return The data at the specified position. */ public T getItem(int position) { if (adapterData == null) { return null; } return adapterData.get(position); } /** * Get the row id associated with the specified position in the list. Note that item IDs are not stable so you * cannot rely on the item ID being the same after {@link #notifyDataSetChanged()} or * {@link #updateData(OrderedRealmCollection)} has been called. * * @param position The position of the item within the adapter's data set whose row id we want. * @return The id of the item at the specified position. */ @Override public long getItemId(int position) { // TODO: find better solution once we have unique IDs return position; } /** * Updates the data associated with the Adapter. * * Note that RealmResults and RealmLists are "live" views, so they will automatically be updated to reflect the * latest changes. This will also trigger {@code notifyDataSetChanged()} to be called on the adapter. * * This method is therefore only useful if you want to display data based on a new query without replacing the * adapter. * * @param data the new {@link OrderedRealmCollection} to display. */ public void updateData(OrderedRealmCollection<T> data) { if (listener != null) { if (adapterData != null) { removeListener(adapterData); } if (data != null) { addListener(data); } } this.adapterData = data; notifyDataSetChanged(); } } 

Это для v0.84.0 И ВЫШЕ, НО ПОСЛЕ ТОГО, что v0.89.0 (обновлено для v0.87.5):

 public abstract class RealmRecyclerViewAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { //put this in `io.realm` protected LayoutInflater inflater; protected RealmResults<T> realmResults; protected Context context; private final RealmChangeListener listener; public RealmRecyclerViewAdapter(Context context, RealmResults<T> realmResults, boolean automaticUpdate) { if (context == null) { throw new IllegalArgumentException("Context cannot be null"); } this.context = context; this.realmResults = realmResults; this.inflater = LayoutInflater.from(context); this.listener = (!automaticUpdate) ? null : new RealmChangeListener() { @Override public void onChange() { notifyDataSetChanged(); } }; if (listener != null && realmResults != null) { realmResults.realm.handlerController.addChangeListenerAsWeakReference(listener); } } /** * Returns how many items are in the data set. * * @return count of items. */ @Override public int getItemCount() { if (realmResults == null) { return 0; } return realmResults.size(); } /** * Returns the item associated with the specified position. * * @param i index of item whose data we want. * @return the item at the specified position. */ public T getItem(int i) { if (realmResults == null) { return null; } return realmResults.get(i); } /** * Returns the current ID for an item. Note that item IDs are not stable so you cannot rely on the item ID being the * same after {@link #notifyDataSetChanged()} or {@link #updateRealmResults(RealmResults)} has been called. * * @param i index of item in the adapter. * @return current item ID. */ @Override public long getItemId(int i) { // TODO: find better solution once we have unique IDs return i; } /** * Updates the RealmResults associated to the Adapter. Useful when the query has been changed. * If the query does not change you might consider using the automaticUpdate feature. * * @param queryResults the new RealmResults coming from the new query. */ public void updateRealmResults(RealmResults<T> queryResults) { if (listener != null) { // Making sure that Adapter is refreshed correctly if new RealmResults come from another Realm if (this.realmResults != null) { this.realmResults.realm.removeChangeListener(listener); } if (queryResults != null) { queryResults.realm.addChangeListener(listener); } } this.realmResults = queryResults; notifyDataSetChanged(); } public void addChangeListenerAsWeakReference(RealmChangeListener realmChangeListener) { if(realmResults != null) { realmResults.realm.handlerController.addChangeListenerAsWeakReference(realmChangeListener); } } } 

Это для более низкого уровня 0.84.0 :

 public abstract class RealmRecyclerViewAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { //put this in `io.realm` protected LayoutInflater inflater; protected RealmResults<T> realmResults; protected Context context; private final RealmChangeListener listener; public RealmRecyclerViewAdapter(Context context, RealmResults<T> realmResults, boolean automaticUpdate) { if(context == null) { throw new IllegalArgumentException("Context cannot be null"); } this.context = context; this.realmResults = realmResults; this.inflater = LayoutInflater.from(context); this.listener = (!automaticUpdate) ? null : new RealmChangeListener() { @Override public void onChange() { notifyDataSetChanged(); } }; if(listener != null && realmResults != null) { realmResults.getRealm() .addChangeListener(listener); } } @Override public long getItemId(int i) { // TODO: find better solution once we have unique IDs return i; } public T getItem(int i) { if(realmResults == null) { return null; } return realmResults.get(i); } public void updateRealmResults(RealmResults<T> queryResults) { if(listener != null) { // Making sure that Adapter is refreshed correctly if new RealmResults come from another Realm if(this.realmResults != null) { realmResults.getRealm().removeChangeListener(listener); } if(queryResults != null) { queryResults.getRealm().addChangeListener(listener); } } this.realmResults = queryResults; notifyDataSetChanged(); } @Override public int getItemCount() { if(realmResults == null) { return 0; } return realmResults.size(); } } 

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

Вот наш AbstractRealmAdapter, который заботится о всех материалах низкого уровня, отображает заголовки, нижние колонтитулы, элементы, загружает данные в RealmResults, управляет типами элементов

 import io.realm.Realm; import io.realm.RealmObject; import io.realm.RealmResults; public abstract class AbstractRealmAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { public static final int HEADER_COUNT = 1; public static final int FOOTER_COUNT = 1; //Our data source protected RealmResults<T> mResults; public AbstractRealmAdapter(Realm realm) { //load data from subclasses mResults = loadData(realm); notifyDataSetChanged(); } public int getHeaderCount() { return hasHeader() ? HEADER_COUNT : 0; } public int getFooterCount() { return hasFooter() ? FOOTER_COUNT : 0; } public boolean isHeader(int position) { if (hasHeader()) { return position < HEADER_COUNT; } else { return false; } } public boolean isFooter(int position) { if (hasFooter()) { return position >= getCount() + getHeaderCount(); } else { return false; } } @Override public long getItemId(int i) { return i; } @Override public final int getItemViewType(int position) { if (isHeader(position)) { return ItemType.HEADER.ordinal(); } else if (isFooter(position)) { return ItemType.FOOTER.ordinal(); } else { return ItemType.ITEM.ordinal(); } } /** * @param position the position within our adapter inclusive of headers,items and footers * @return an item only if it is not a header or a footer, otherwise returns null */ public T getItem(int position) { if (!isHeader(position) && !isFooter(position) && !mResults.isEmpty()) { return mResults.get(position - getHeaderCount()); } return null; } @Override public final int getItemCount() { return getHeaderCount() + getCount() + getFooterCount(); } public final int getCount() { return mResults.size(); } public abstract boolean hasHeader(); public abstract boolean hasFooter(); public void setData(RealmResults<T> results) { mResults = results; notifyDataSetChanged(); } protected abstract RealmResults<T> loadData(Realm realm); public enum ItemType { HEADER, ITEM, FOOTER; } } 

Чтобы добавить элементы каким-либо способом или удалить элементы путем удаления, у нас есть расширение в виде AbstractMutableRealmAdapter, которое выглядит как показано ниже

 import android.support.v7.widget.RecyclerView; import io.realm.Realm; import io.realm.RealmObject; public abstract class AbstractMutableRealmAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends AbstractRealmAdapter<T, VH> implements OnSwipeListener { private Realm realm; public AbstractMutableRealmAdapter(Realm realm) { //call the superclass constructor to load data from subclasses into realmresults super(realm); this.realm = realm; } public void add(T item, boolean update) { realm.beginTransaction(); T phraseToWrite = (update == true) ? realm.copyToRealmOrUpdate(item) : realm.copyToRealm(item); realm.commitTransaction(); notifyItemRangeChanged(0, mResults.size()); } @Override public final void onSwipe(int position) { if (!isHeader(position) && !isFooter(position) && !mResults.isEmpty()) { int itemPosition = position - getHeaderCount(); realm.beginTransaction(); T item = mResults.get(itemPosition); item.removeFromRealm(); realm.commitTransaction(); notifyItemRemoved(position); } } } 

Обратите внимание на использование интерфейса OnSwipeListener, который выглядит так:

 public interface OnSwipeListener { /** * @param position the position of the item that was swiped within the RecyclerView */ void onSwipe(int position); } 

Этот SwipeListener используется для выполнения Swipe для удаления внутри нашего TouchHelperCallback, который, в свою очередь, используется для прямого удаления объектов из Realm и выглядит следующим образом

 import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; public class TouchHelperCallback extends ItemTouchHelper.Callback { private final OnSwipeListener mSwipeListener; public TouchHelperCallback(OnSwipeListener adapter) { mSwipeListener = adapter; } /** * @return false if you dont want to enable drag else return true */ @Override public boolean isLongPressDragEnabled() { return false; } /** * @return true of you want to enable swipe in your RecyclerView else return false */ @Override public boolean isItemViewSwipeEnabled() { return true; } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //We want to let the person swipe to the right on devices that run LTR and let the person swipe from right to left on devices that run RTL int swipeFlags = ItemTouchHelper.END; return makeMovementFlags(0, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mSwipeListener.onSwipe(viewHolder.getAdapterPosition()); } } 

Полная демонстрация реализации доступна здесь для просмотра https://github.com/slidenerd/SpamWordList/tree/spamphraser_with_realmresults_base Не стесняйтесь предлагать какие-либо улучшения

Я заменил методы notifyXXX объектами notifyDataSetChanged, RealmResults – это живые объекты, что означает, что они автоматически меняются при обновлении данных, я пытался использовать методы notifyXXX, и они вызвали исключение несоответствия RecyclerView, я хорошо осведомлен о том, что notifyDataSetChanged () С анимацией, заставит вас, ребята, обновить решение, которое преодолеет ошибку несогласованности и в то же время обеспечит хороший адаптер

Теперь, когда в Realm 0.88.2 мы можем сделать адаптер RecyclerView, который обновляет RecyclerView с большей точностью, чем использование notifyDataSetChanged () каждый раз. Это может быть достигнуто с помощью новой возможности создания пользовательских методов.

Переопределение метода equals, в объекте realm, которое будет использоваться с адаптером recycler, – все, что потребуется. (На самом деле вам не нужно переопределять равные … но вы можете обнаружить, что объекты сферы не совпадают друг с другом, когда вы их ожидаете. Это приведет к ненужным обновлениям recyclerview после запуска diff)

Затем добавьте java-diff-utils Google в свои зависимости от градиента

  compile 'com.googlecode.java-diff-utils:diffutils:1.3.0' 

Используя эту реализацию RealmRecyclerViewAdapter, копия realmResults выполняется при запуске и при каждом изменении для сравнения с будущими изменениями. Обнаруженные изменения используются для обновления RecyclerView по мере необходимости

 public abstract class RealmRecyclerViewAdapter<T extends RealmObject, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { protected RealmResults<T> realmResults; protected List<T> lastCopyOfRealmResults; int maxDepth = 0; private RealmChangeListener realmResultsListener; Realm realm; public RealmRecyclerViewAdapter(RealmResults<T> realmResults, boolean automaticUpdate) { this(realmResults, automaticUpdate, 0); } /** * * @param realmResults * @param automaticUpdate * @param maxDepth limit of the deep copy when copying realmResults. All references after this depth will be {@code null}. Starting depth is {@code 0}. * A copy of realmResults is made at start, and on every change to compare against future changes. Detected changes are used to update * the RecyclerView as appropriate */ public RealmRecyclerViewAdapter(RealmResults<T> realmResults, boolean automaticUpdate, int maxDepth) { this.realmResultsListener = (!automaticUpdate) ? null : getRealmResultsChangeListener(); if (realmResultsListener != null && realmResults != null) { realmResults.addChangeListener(realmResultsListener); } this.realmResults = realmResults; realm = Realm.getDefaultInstance(); this.maxDepth = maxDepth; lastCopyOfRealmResults = realm.copyFromRealm(realmResults, this.maxDepth); } @Override public int getItemCount() { return realmResults != null ? realmResults.size() : 0; } /** * Make sure this is called before a view is destroyed to avoid memory leaks do to the listeners. * Do this by calling setAdapter(null) on your RecyclerView * @param recyclerView */ @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { super.onDetachedFromRecyclerView(recyclerView); if (realmResultsListener != null) { if (realmResults != null) { realmResults.removeChangeListener(realmResultsListener); } } realm.close(); } /** * Update the RealmResults associated with the Adapter. Useful when the query has been changed. * If the query does not change you might consider using the automaticUpdate feature. * * @param queryResults the new RealmResults coming from the new query. * @param maxDepth limit of the deep copy when copying realmResults. All references after this depth will be {@code null}. Starting depth is {@code 0}. * A copy of realmResults is made at start, and on every change to compare against future changes. Detected changes are used to update * the RecyclerView as appropriate */ public void updateRealmResults(RealmResults<T> queryResults, int maxDepth) { if (realmResultsListener != null) { if (realmResults != null) { realmResults.removeChangeListener(realmResultsListener); } } realmResults = queryResults; if (realmResults != null && realmResultsListener !=null) { realmResults.addChangeListener(realmResultsListener); } this.maxDepth = maxDepth; lastCopyOfRealmResults = realm.copyFromRealm(realmResults,this.maxDepth); notifyDataSetChanged(); } public T getItem(int position) { return realmResults.get(position); } public int getRealmResultsSize(){ return realmResults.size(); } private RealmChangeListener getRealmResultsChangeListener() { return new RealmChangeListener<RealmResults<T>>() { @Override public void onChange(RealmResults<T> element) { if (lastCopyOfRealmResults != null && !lastCopyOfRealmResults.isEmpty()) { if (realmResults.isEmpty()) { // If the list is now empty, just notify the recyclerView of the change. lastCopyOfRealmResults = realm.copyFromRealm(realmResults,maxDepth); notifyDataSetChanged(); return; } Patch patch = DiffUtils.diff(lastCopyOfRealmResults, realmResults); List<Delta> deltas = patch.getDeltas(); lastCopyOfRealmResults = realm.copyFromRealm(realmResults,maxDepth); if (!deltas.isEmpty()) { List<Delta> deleteDeltas = new ArrayList<>(); List<Delta> insertDeltas = new ArrayList<>(); for (final Delta delta : deltas) { switch (delta.getType()){ case DELETE: deleteDeltas.add(delta); break; case INSERT: insertDeltas.add(delta); break; case CHANGE: notifyItemRangeChanged( delta.getRevised().getPosition(), delta.getRevised().size()); break; } } for (final Delta delta : deleteDeltas) { notifyItemRangeRemoved( delta.getOriginal().getPosition(), delta.getOriginal().size()); } //item's should be removed before insertions are performed for (final Delta delta : insertDeltas) { notifyItemRangeInserted( delta.getRevised().getPosition(), delta.getRevised().size()); } } } else { notifyDataSetChanged(); lastCopyOfRealmResults = realm.copyFromRealm(realmResults,maxDepth); } } }; } } 

В вашем сообщении нет даже реального вопроса.

Вы проверили этот пост: http://gradlewhy.ghost.io/realm-results-with-recyclerview/ ?

Не уверен, почему вы не просто используете ArrayList в своем адаптере и добавите все элементы из RealmResult в этот список. Может ли кто-нибудь объяснить, почему решение в блоге лучше?

Реализация надстройки Realm от Thorben Primke – очень удобный метод обработки приложений Recycler View с базами данных Realm. Его github имеет хорошие примеры того, как он может быть реализован.

Я включу здесь, чтобы у вас был пример. Сначала измените градиент построения проекта для jitpack.io:

 allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } 

Затем ваш градиент модуля укажет на библиотеку: (обратите внимание, проверьте последнюю версию)

 dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.github.thorbenprimke:realm-recyclerview:0.9.20' 

Создайте макет xml для просмотра ресайклеров с помощью RealmRecyclerView:

  <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="wrap_content"> <co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView android:id="@+id/realm_recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" app:rrvIsRefreshable="true" app:rrvEmptyLayoutId="@layout/empty_view" app:rrvLayoutType="LinearLayout" app:rrvSwipeToDelete="true" /> </RelativeLayout> 

Теперь в вашем фрагменте RealmRecycler получите запрос Realm-запроса RealmObjects, раздуйте и определите Primk RealmAdapter:

  Log.i(TAG, " Obtain Filtered List"); final RealmResults <Session> realmResults = queryD.findAllSorted( "sessionId", Sort.DESCENDING); Log.i(TAG, " Inflate realm List"); View view = inflater.inflate(R.layout.realm_card_recycler2, null); Log.i(TAG, " Define and configure SessionRealmAdapter"); SessionRealmAdapter sessionRealmAdapter = new SessionRealmAdapter(getActivity(), realmResults, true, true);`enter code here` RealmRecyclerView realmRecyclerView = (RealmRecyclerView) view.findViewById(R.id.realm_recycle_view); realmRecyclerView.setAdapter(sessionRealmAdapter); 

Наконец настройте адаптер Realm для любых действий. У меня есть пара для кликов и для удаления записей в режиме реального времени.

  public class SessionRealmAdapter extends RealmBasedRecyclerViewAdapter<Session, SessionRealmAdapter.ViewHolder> { public class ViewHolder extends RealmViewHolder { public TextView sessionTextView; public ViewHolder(FrameLayout container) { super(container); this.sessionTextView = (TextView) container.findViewById(R.id.session_text_view); } } public SessionRealmAdapter( Context context, RealmResults<Session> realmResults, boolean automaticUpdate, boolean animateResults) { super(context, realmResults, automaticUpdate, animateResults); } @Override public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) { View v = inflater.inflate(R.layout.session_simple_view, viewGroup, false); return new ViewHolder((FrameLayout) v); } @Override public void onBindRealmViewHolder(ViewHolder viewHolder, int position) { final Session singleSession = realmResults.get(position); viewHolder.sessionTextView.setText(singleSession.gettMethod()); viewHolder.sessionTextView.setOnClickListener( new View.OnClickListener(){ @Override public void onClick(View v){ selectSession(singleSession); showMessage(" Selected "+singleSession.gettMethod()); } } ); viewHolder.sessionTextView.setOnLongClickListener( new View.OnLongClickListener(){ @Override public boolean onLongClick(View v){ showInformationDialog(singleSession); showMessage("Long click selected for " +singleSession.getSessionTitle()); return true; } } ); } }