In my last blog has introduced the implementation of the top function in ListView, and then also want to achieve a very popular RecyclerView, so I wrote this blog. If you have not read before, it is recommended to read the Android ListView implementation top function.

The effect is shown in the picture.




In fact, the principle is still the same, that is, the adapter in RecyclerView is inherited from RecyclerView. Adapter, that is to say, it does not provide the ArrayAdapter that we need, so I was just, Wouldn’t you have to write it yourself? TnT

But WITTY I still Google first, sure enough is Google big law good ah, I found a foreign giant has written a good ArrayAdapter for RecyclerView ArrayAdapter

I read his source code feel preliminary meet my needs ah, and then decisively get it! Then on its basis to modify the code, to meet my use requirements. The code is as follows:

public abstract class RecyclerArrayAdapter extends RecyclerView.Adapter { private List mObjects; public RecyclerArrayAdapter(final List objects) { mObjects = objects; } /** * Adds the specified object at the end of the array. * * @param object The object to add at the end of the array. */ public void add(final T object) { mObjects.add(object); notifyItemInserted(getItemCount() - 1); } /** * Remove all elements from the list. */ public void clear() { final int size = getItemCount(); mObjects.clear(); notifyItemRangeRemoved(0, size); } @Override public int getItemCount() { return mObjects.size(); } public T getItem(final int position) { return mObjects.get(position); } public long getItemId(final int position) { return position; } /** * Returns the position of the specified item in the array. * * @param item The item to retrieve the position of. *  @return The position of the specified item. */ public int getPosition(final T item) { return mObjects.indexOf(item); } /** * Inserts the specified object at the specified index in the array. * * @param object The object to insert into the array. * @param index The index at which the object must be inserted. */ public void insert(final T object, int index) { mObjects.add(index, object); notifyItemInserted(index); } /** * Removes the specified object from the array. * * @param object The object to remove. */ public void remove(T object) { final int position = getPosition(object); mObjects.remove(object); notifyItemRemoved(position); } /** * Sorts the content of this adapter using the specified comparator. * * @param comparator The comparator used to sort the objects contained in this adapter. */ public void sort(Comparator comparator) { Collections.sort(mObjects, comparator); notifyItemRangeChanged(0, getItemCount()); Public void addAll(List List) {final int size = getItemCount(); mObjects.addAll(list); notifyItemRangeChanged(0, size); }}Copy the code

As can be seen from the code, this is a generic abstract class inherited from recyclerView. adapter, through the generic T to bind the data type, in the class using mObjects this linked list to maintain data operations, and at the same time notify the update of recyclerView. adapter, If you are not familiar with these notification methods, you can go to the official documentation, which will not be detailed here.

And as you can see, I just added the addAll() method =_= because, as I said in the last blog post, this method is needed for real-time top interactions.

OK! So there we have our ArrayAdapter. Then we’re on to the next step! Let’s use this packaged ArrayAdapter as follows:

public class RecyclerViewAdapter extends RecyclerArrayAdapter { private LayoutInflater mInflater; private ItemOnLongClickListener itemListener; public RecyclerViewAdapter(Context context) { super(new ArrayList()); mInflater = LayoutInflater.from(context); } @Override public void onBindViewHolder(RecyclerViewHolder holder, final int position) { Session session = getItem(position); holder.textView.setText(String.valueOf(session.getTop())); holder.imageView.setImageResource(session.getAvatar()); / / their implementation itemClickListener holder. MItemView. SetOnLongClickListener (new View. OnLongClickListener () {@ Override public Boolean onLongClick (View v) {/ / callback itemListener. ItemLongClick (the getItem (position)); return false; }}); if (session.getTop() == 1) { holder.mItemView.setBackgroundResource(R.drawable.bg_top_item_selector); } else { holder.mItemView.setBackgroundResource(R.drawable.bg_item_selector); } } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {RecyclerView match parent int RecyclerView match parent int return new RecyclerViewHolder(mInflater.inflate(R.layout.itemview, parent, false)); } public void setItemListener(ItemOnLongClickListener listener) { itemListener = listener; } public void updateData(List list) { clear(); addAll(list); } public static class RecyclerViewHolder extends RecyclerView.ViewHolder { TextView textView; ImageView imageView; View mItemView; public RecyclerViewHolder(View itemView) { super(itemView); mItemView = itemView; textView = (TextView) itemView.findViewById(R.id.textView); imageView = (ImageView) itemView.findViewById(R.id.avatar_img); } } public interface ItemOnLongClickListener { void itemLongClick(Session session); }}Copy the code

As the code can be seen, we inherit the generic abstract class ArrayAdapter, RecyclerView needs to achieve the Adapter, the implementation is very simple, is a common adapter.

Because RecyclerView does not have itemClick listener, so this to achieve their own click event callback, I believe used should know. In addition, through the implementation of ArrayAdapter can be found that RecyclerView is indeed relatively high decoupling, although the amount of code is a little bit more, but the logic is clear, controllability is also very good, worth in-depth use.

The next step is interaction, which is similar to what I said in my last blog post, but because it’s a different RecyclerView, different code to handle.

Dialogfragment is also used as a form to switch the top, even the code does not need to change it…

public class PopupDialogFragment extends DialogFragment { private DialogItemOnClickListener itemOnClickListener; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.popview, null); TextView onTopTv = (TextView) view.findViewById(R.id.on_top_tv); TextView cancelTv = (TextView) view.findViewById(R.id.cancel_top_tv); Bundle bundle = getArguments(); int isTop = bundle.getInt(MainActivity.TOP_STATES); if (isTop == 1) { onTopTv.setVisibility(View.GONE); cancelTv.setVisibility(View.VISIBLE); } else if (isTop == 0) { onTopTv.setVisibility(View.VISIBLE); cancelTv.setVisibility(View.GONE); } onTopTv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getDialog().dismiss();  itemOnClickListener.onTop(); }}); cancelTv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getDialog().dismiss(); itemOnClickListener.onCancel(); }}); getDialog().getWindow().requestFeature(STYLE_NO_TITLE); setStyle(STYLE_NO_FRAME, android.R.style.Theme_Light); setCancelable(true); getDialog().getWindow().setBackgroundDrawableResource(R.color.write_bg); return view; } public void setItemOnClickListener(DialogItemOnClickListener itemOnClickListener) { this.itemOnClickListener = itemOnClickListener; } public interface DialogItemOnClickListener { void onTop(); void onCancel(); }}Copy the code

Next comes the callback, which is implemented in MainActivity as follows:

mRecyclerViewAdapter.setItemListener(new RecyclerViewAdapter.ItemOnLongClickListener() { @Override public void itemLongClick(final Session session) { Bundle bundle = new Bundle(); bundle.putInt(TOP_STATES, session.getTop()); PopupDialogFragment popupDialog = new PopupDialogFragment(); popupDialog.setArguments(bundle); popupDialog.setItemOnClickListener(new PopupDialogFragment.DialogItemOnClickListener() { @Override public void onTop() { / / set-top session. SetTop (1); session.setTime(System.currentTimeMillis()); refreshView(); } @override public void onCancel() {// Cancel session.settop (0); session.setTime(System.currentTimeMillis()); refreshView(); }}); popupDialog.show(getFragmentManager(), "popup"); }});Copy the code

Finally, the same unchanged Session, to achieve the top data sort, the code is as follows:

Public class Session implements Serializable, Comparable {/** ** * public int top; /** ** public long time; /** ** public int avatar; public long getTime() { return time; } public void setTime(long time) { this.time = time; } public int getTop() { return top; } public void setTop(int top) { this.top = top; } public int getAvatar() { return avatar; } public void setAvatar(int avatar) { this.avatar = avatar; } @Override public int compareTo(Object another) { if (another == null || ! (another instanceof Session)) { return -1; } Session otherSession = (Session) another; /** ArrayAdapters are sorted in ascending order from top to bottom, which is the default natural sort. * if the array is equal, return 0. If the array is not equal, return 0. So if the otherSession is top-ranked, the current session is non-top-ranked, it should be below the otherSession, so return 1 * and if the session is top-ranked, the current otherSession is non-top-ranked, it should be above the otherSession, Return -1 * */ int result = 0 - (top-othersession.getTop ()); if (result == 0) { result = 0 - compareToTime(time, otherSession.getTime()); } return result; } public static int compareToTime(long LHS, long RHS) {Calendar cLhs = Calendar. GetInstance (); Calendar cRhs = Calendar.getInstance(); cLhs.setTimeInMillis(lhs); cRhs.setTimeInMillis(rhs); return cLhs.compareTo(cRhs); }}Copy the code

That’s all, click here to get the source code GitHub address