Skip to content

Instantly share code, notes, and snippets.

@tprochazka
Created February 27, 2016 23:36
Show Gist options
  • Save tprochazka/3129de6e6ad8f6ff37aa to your computer and use it in GitHub Desktop.
Save tprochazka/3129de6e6ad8f6ff37aa to your computer and use it in GitHub Desktop.
Example of solution for universal RecyclerViewAdapter
/**
* View that can be used with this adapter must implement this interfaces.
*/
public interface ISettableView<T> {
void setData(T item);
void setEventListener(RecylerViewAdapter.ViewItemEventListener<T> listener);
}
public class RecylerViewAdapter<T> extends RecyclerView.Adapter<RecylerViewAdapter.DummyViewHolder> {
private final Context mContext;
protected List<T> mList;
protected int mLayoutId;
private boolean mNotifyOnChange = true;
private final LayoutInflater mLayoutInflater;
private ViewItemEventListener<T> mEventListener;
public RecylerViewAdapter(Context context, List<T> list, int layoutId) {
mContext = context;
mList = list;
mLayoutId = layoutId;
mLayoutInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public RecylerViewAdapter(Context context, int layoutId) {
this(context, new ArrayList<T>(), layoutId);
}
/**
* Set callback for item event.
*/
public void setEventListener(RecylerViewAdapter.ViewItemEventListener<T> listener) {
mEventListener = listener;
}
/**
* Replace current data with new one.
*/
public void setData(List<? extends T> newList) {
mList = (List<T>)newList;
if (mNotifyOnChange) notifyDataSetChanged();
}
/**
* Add new list at the end of the current.
*/
public void addData(List<? extends T> newList) {
if (newList == null) {
return;
}
if (mList == null) {
mList = new ArrayList<>();
}
int originalCount = mList.size();
mList.addAll(newList);
if (mNotifyOnChange) notifyItemRangeInserted(originalCount-1, mList.size());
}
/**
* Will replace data from selected position
*/
public void replaceData(int position, List<? extends T> newList) {
if (mList == null) {
mList = new ArrayList<>();
}
for (T t : newList) {
if (position < mList.size()) {
mList.set(position, t);
} else {
mList.add(position, t);
}
position++;
}
if (mNotifyOnChange) notifyItemRangeChanged(position, newList.size());
}
public void removeItem(int position) {
mList.remove(position);
if (mNotifyOnChange) notifyItemRemoved(position);
}
public void insertItem(int position, T item) {
mList.add(position, item);
if (mNotifyOnChange) notifyItemInserted(position);
}
public void removeItem(T item) {
int position = mList.indexOf(item);
mList.remove(item);
if (mNotifyOnChange) notifyItemRemoved(position);
}
public void addItem(T item) {
mList.add(item);
if (mNotifyOnChange) notifyItemInserted(mList.size() - 2);
}
/**
* Remove all elements from the list.
*/
public void clear() {
if (mList != null) {
synchronized (mList) {
mList = new ArrayList<>();
}
}
if (mNotifyOnChange) notifyDataSetChanged();
}
/**
* Control whether methods that change the list will automatically call {@link #notifyDataSetChanged}.
* <p/>
* If set to false, caller must manually call notifyDataSetChanged() to have the changes
* reflected in the attached view.
* <p/>
* The default is true, and calling notifyDataSetChanged() resets the flag to true.
*
* @param notifyOnChange if true, modifications to the list will automatically call {@link
* #notifyDataSetChanged}
*/
public void setNotifyOnChange(boolean notifyOnChange) {
mNotifyOnChange = notifyOnChange;
}
@Override
public DummyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = mLayoutInflater.inflate(mLayoutId, parent, false);
((ISettableView<T>)view).setEventListener(mEventListener);
return new DummyViewHolder(view);
}
@Override
public void onBindViewHolder(DummyViewHolder holder, final int position) {
final View view = holder.itemView;
((ISettableView<T>)view).setData(mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
static class DummyViewHolder extends RecyclerView.ViewHolder {
public DummyViewHolder(View itemView) {
super(itemView);
}
}
// TODO
public interface ViewItemEventListener<T> {
/**
* Called on single click.
*
* @param item adapter item
* @param partIdentifier used to identify part of view if it is not clickable as one piece.
*/
void onClick(@NonNull T item, int partIdentifier);
/**
* Called on single click.
*
* @param item adapter item
* @param partIdentifier used to identify part of view if it is not clickable as one piece.
*/
void onLongClick(@NonNull T item, int partIdentifier);
/**
* Called when popup menu is created.
*
* @param menuInflater MenuInflater that can be used to inflate menu items from XML into the menu returned by
* getMenu().
* @param menu Menu associated with this popup. Populate the returned Menu with items.
* @param item of view that was clicked.
*/
void onCreateOverflowMenu(@NonNull MenuInflater menuInflater, @NonNull Menu menu, @NonNull T item);
/**
* Called when popup menu item is selected.
*
* @param menuItem MenuItem that was clicked
* @param item of view that displayed popup menu
* @return true if popup menu item selection is handled
*/
boolean onOverflowMenuItemSelected(@NonNull MenuItem menuItem, @NonNull T item);
}
public static abstract class AbstractViewItemEventListener<T> implements ViewItemEventListener<T> {
@Override
public void onClick(@NonNull T item, int partIdentifier) {
}
@Override
public void onLongClick(@NonNull T item, int partIdentifier) {
}
@Override
public void onCreateOverflowMenu(@NonNull MenuInflater menuInflater, @NonNull Menu menu, @NonNull T item) {
}
@Override
public boolean onOverflowMenuItemSelected(@NonNull MenuItem menuItem, @NonNull T item) {
return false;
}
}
}
@vtb1975
Copy link

vtb1975 commented Dec 23, 2021

May you please to write a small example to implement interface ISettableView in View Model?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment