Skip to content

Instantly share code, notes, and snippets.

@puke3615
Last active July 14, 2021 07:32
Show Gist options
  • Save puke3615/825c28f46423cf735299505c80033c67 to your computer and use it in GitHub Desktop.
Save puke3615/825c28f46423cf735299505c80033c67 to your computer and use it in GitHub Desktop.
RecyclerViewHelper
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 封装{@link RecyclerView}辅助类<br/>
* 主要为了简化使用单ItemType的RecyclerView时冗余的{@link RecyclerView.ViewHolder}和{@link RecyclerView.Adapter}设置流程
*
* @author puke
* @version 2021/5/26
*/
public class RecyclerViewHelper<T> {
private final RecyclerView recyclerView;
private final ItemViewFactory itemViewFactory;
private final HolderRenderer<T> holderRenderer;
private final Adapter adapter;
private final List<T> dataList = new ArrayList<>();
public static <T> RecyclerViewHelper<T> of(@NonNull RecyclerView recyclerView,
@LayoutRes int itemLayoutRes,
@NonNull HolderRenderer<T> holderRenderer) {
return new RecyclerViewHelper<>(recyclerView, parent -> {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return inflater.inflate(itemLayoutRes, parent, false);
}, holderRenderer);
}
private RecyclerViewHelper(@NonNull RecyclerView recyclerView,
@NonNull ItemViewFactory itemViewFactory,
@NonNull HolderRenderer<T> holderRenderer) {
this.recyclerView = recyclerView;
this.itemViewFactory = itemViewFactory;
this.holderRenderer = holderRenderer;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager == null) {
recyclerView.setLayoutManager(new LinearLayoutManager(
recyclerView.getContext(), LinearLayoutManager.VERTICAL, false));
}
adapter = new Adapter();
recyclerView.setAdapter(adapter);
}
/**
* 设置新数据源
*
* @param newData 新数据源
*/
public void setData(List<T> newData) {
dataList.clear();
if (newData != null) {
dataList.addAll(newData);
}
adapter.notifyDataSetChanged();
}
/**
* 添加数据源
*
* @param addedData 新增的数据源
*/
public void addData(List<T> addedData) {
if (addedData != null && addedData.size() > 0) {
int originSize = dataList.size();
dataList.addAll(addedData);
adapter.notifyItemRangeInserted(originSize, originSize);
}
}
/**
* 移除数据
*
* @param position 待移除数据的索引值
*/
public void removeData(int position) {
if (position >= 0 && position < dataList.size()) {
dataList.remove(position);
adapter.notifyItemRemoved(position);
}
}
public int getItemCount() {
return adapter.getItemCount();
}
/**
* @return 当前的RecyclerView对象
*/
public RecyclerView getRecyclerView() {
return recyclerView;
}
/**
* @return 数据源 (注: 不可更改)
*/
public List<T> getDataList() {
return Collections.unmodifiableList(dataList);
}
private class Adapter extends RecyclerView.Adapter<ViewHolder> {
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// ItemView具体的构造逻辑, 回调给外部处理
View itemView = itemViewFactory.getItemView(parent);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
// 获取当前数据模型
T model = dataList.get(position);
// 通过渲染器回调, 将真实的数据回调抛出去
holderRenderer.render(holder, model, position, getItemCount());
}
@Override
public int getItemCount() {
return dataList.size();
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final SparseArray<View> viewCaches = new SparseArray<>();
ViewHolder(@NonNull View itemView) {
super(itemView);
}
@SuppressWarnings("unchecked")
public <V extends View> V getView(@IdRes int id) {
// 使用ViewCache来解决"抽象层无法穷举成员变量"和"重复findViewById调用"的冲突
View view = viewCaches.get(id);
if (view == null) {
view = itemView.findViewById(id);
viewCaches.put(id, view);
}
return (V) view;
}
}
/**
* ItemView工厂类
*/
public interface ItemViewFactory {
@NonNull
View getItemView(ViewGroup parent);
}
/**
* ViewHolder渲染器
*
* @param <T> 数据模型
*/
public interface HolderRenderer<T> {
void render(ViewHolder holder, T model, int position, int itemCount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment