Best practices to use realm with a recycler view?

前端 未结 5 645
再見小時候
再見小時候 2020-12-04 15:54

Do you guys have any best practices regarding using realm with a recyclerview ? I know it\'s generic question but I found nothing on it on the internet. For example I run in

5条回答
  •  自闭症患者
    2020-12-04 16:37

    ANSWER FOR 0.89.0 AND ABOVE

    For the latest versions, you should use RealmRecyclerViewAdapter in the realm-android-adapters repository.

    Versions:

    • Use 1.5.0 up to 2.X

    • Use 2.1.1 up to 4.X

    • Use 3.0.0 above 5.X


    OLD ANSWER FOR OLD VERSIONS:

    I made this RealmRecyclerViewAdapter based on the implementation of RealmBaseAdapter.

    This is for v0.89.0 AND ABOVE

    public abstract class RealmRecyclerViewAdapter
        extends RecyclerView.Adapter { //put this in `io.realm`
    
        protected LayoutInflater inflater;
        protected OrderedRealmCollection adapterData;
        protected Context context;
        private final RealmChangeListener listener;
    
        public RealmRecyclerViewAdapter(Context context, OrderedRealmCollection 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>() {
                @Override
                public void onChange(RealmResults results) {
                    notifyDataSetChanged();
                }
            };
    
            if (data != null) {
                addListener(data);
            }
        }
    
        private void addListener(OrderedRealmCollection 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 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 data) {
            if (listener != null) {
                if (adapterData != null) {
                    removeListener(adapterData);
                }
                if (data != null) {
                    addListener(data);
                }
            }
    
            this.adapterData = data;
            notifyDataSetChanged();
        }
    }
    

    This is for v0.84.0 AND ABOVE, BUT OLDER THAN v0.89.0 (updated for v0.87.5):

    public abstract class RealmRecyclerViewAdapter
            extends RecyclerView.Adapter { //put this in `io.realm`
        protected LayoutInflater inflater;
        protected RealmResults realmResults;
        protected Context context;
        private final RealmChangeListener listener;
    
        public RealmRecyclerViewAdapter(Context context, RealmResults 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 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);
            }
        }
    }
    

    This is for OLDER THAN 0.84.0:

    public abstract class RealmRecyclerViewAdapter
            extends RecyclerView.Adapter { //put this in `io.realm`
        protected LayoutInflater inflater;
        protected RealmResults realmResults;
        protected Context context;
    
        private final RealmChangeListener listener;
    
        public RealmRecyclerViewAdapter(Context context, RealmResults 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 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();
        }
    }
    

提交回复
热议问题