sociales reciclapp reciclaje recicladores proyectos programa para inclusivo funciona definicion con comunas como chile app aplicaciones android android-recyclerview realm

android - reciclapp - reciclaje inclusivo definicion



¿Mejores prácticas para usar el reino con una vista de reciclador? (5)

Ahora que con Realm 0.88.2 podemos hacer un adaptador RecyclerView que actualice RecyclerView con más precisión que si se utiliza el comando NotifyDataSetChanged () cada vez. Esto se puede lograr usando la nueva capacidad de crear métodos personalizados.

Anular el método equals, en el objeto de reino que se utilizará con el adaptador de reciclador, es todo lo que se necesitará. (En realidad, no es necesario anular los iguales ... pero es posible que los objetos del reino no sean iguales entre sí cuando espera que lo hagan. Esto llevará a actualizaciones de recyclerview innecesarias después de ejecutar diff)

A continuación, agregue java-diff-utils de Google a sus dependencias de gradle

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

Al utilizar esta implementación de RealmRecyclerViewAdapter, se realiza una copia de realmResults al inicio y en cada cambio para comparar con cambios futuros. Los cambios detectados se utilizan para actualizar RecyclerView según corresponda

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

¿Tienen alguna práctica recomendada con respecto al uso del reino con un recyclerview? Sé que es una pregunta genérica pero no encontré nada en ella en internet. Por ejemplo, me encuentro con muchos problemas al intentar implementar un simple cambio de color en una fila. Por ejemplo, considere este uso típico:

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 }

Me encontré con muchos problemas ya que no podía encontrar nada en Internet. Sé que esto se debe a que no sé cómo usar correctamente el reino. Pero encontrar el camino correcto es una lucha en sí misma. Leí toda su documentación pero en vano.

EDITAR: Desde que me pidieron que -> En lugar de decir "Tengo un montón de problemas con [eso]", describa su (s) problema (s) e intentaremos proporcionar información y respuestas a sus incomprensiones.

Así que mi problema es simple:

Tengo un 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; } }

Que puse en una matriz de RealmResults usando:

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

Paso mi matriz de usuario a mi adaptador de usuario personalizado:

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. }

Eso tiene una escucha de clics personalizada: obtiene el elemento recyclerview en el que se hizo clic usando:

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) { } }

Que agrego a mi recyclerView con 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); } }));


Algunas de las respuestas anteriores incluyen la reflexión, sin mencionar que un RecyclerView seccionado causaría complicaciones. Tampoco admiten la adición y eliminación de elementos. Aquí está mi versión del Adaptador RecyclerView que funciona con Realm, admite un RecyclerView seccionado, también agrega y elimina elementos en posiciones arbitrarias si es necesario

Aquí está nuestro AbstractRealmAdapter que se encarga de todas las cosas de bajo nivel, mostrando encabezados, pies de página, elementos, cargando datos dentro de RealmResults, administrando tipos de elementos

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

Para agregar elementos por algún método o eliminar elementos al deslizar para eliminar, tenemos una extensión en la forma de AbstractMutableRealmAdapter que se ve como se muestra a continuación

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

Observe el uso de la interfaz OnSwipeListener que tiene este aspecto

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

Este SwipeListener se utiliza para realizar un Swipe para eliminar dentro de nuestro TouchHelperCallback, que a su vez se utiliza para eliminar los objetos de Realm directamente y tiene el siguiente aspecto

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

La demostración completa de la implementación está disponible aquí para su revisión https://github.com/slidenerd/SpamWordList/tree/spamphraser_with_realmresults_base dude en sugerir cualquier mejora

Reemplazé los métodos NotifyXXX con notifyDataSetChanged, los objetos RealmResults son objetos vivos, lo que significa que cambian automáticamente cuando se actualizan los datos. Intenté llamar a los métodos NotifyXXX y causaron una excepción de inconsistencia en RecyclerView. Con animaciones, los mantendremos informados sobre una solución que supera el error de inconsistencia y al mismo tiempo proporciona una buena experiencia de adaptador.


La implementación del complemento Realm desde Thorben Primke es un método muy conveniente para manejar las aplicaciones de Recycler View con bases de datos Realm. Su github tiene buenos ejemplos de las formas en que se puede implementar.

Incluiré el mío aquí para que tengas un ejemplo. Primero modifique su proyecto, compile gradle para jitpack.io:

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

Luego, su módulo gradle para apuntar a la biblioteca: (nota, verifique la última versión)

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

Cree el diseño xml para una vista de reciclador utilizando 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>

Ahora, en tu Fragmento de RealmRecycler, obtén un resultado de consulta de RealmObjects, infla y define un Adaptador Realm de Primke:

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

Finalmente, configure el adaptador de reino para lo que quiera para las acciones. Tengo un par de clics y activé el deslizamiento para eliminar para eliminar registros de reino.

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


Tu publicación ni siquiera contiene una pregunta real.

¿Ha revisado esta publicación: http://gradlewhy.ghost.io/realm-results-with-recyclerview/ ?

Sin embargo, no estoy seguro de por qué no usaría un ArrayList en su adaptador y agregaría todos los elementos de RealmResult a esa lista. ¿Alguien podría explicar por qué la solución en la publicación del blog sería mejor?


RESPUESTA PARA 0.89.0 Y ARRIBA

Para las últimas versiones, debe usar RealmRecyclerViewAdapter en el repositorio de adaptadores de Android de realm.

Versiones:

  • Utilice 1.5.0 hasta 2.X

  • Utilice 2.1.1 hasta 4.X

  • Utilice 3.0.0 por encima de 5.X

ANTIGUA RESPUESTA PARA VERSIONES ANTIGUAS:

Hice este RealmRecyclerViewAdapter basado en la implementación de RealmBaseAdapter .

Esto es para v0.89.0 y ARRIBA

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

Esto es para v0.84.0 Y ARRIBA, PERO MÁS QUE V0.89.0 (actualizado para 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); } } }

Esto es para MAYORES DE 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(); } }