一、使用ViewHolder提升性能
在Android 5.0以前,RecyclerView使用ViewHolder来重用布局并减少内存消耗。ViewHolder是一个包含视图组件的容器,可以提高视图重用的效率。我们可以通过继承RecyclerView.ViewHolder来创建ViewHolder。
class MyViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView age;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
age = (TextView) view.findViewById(R.id.age);
}
}
ViewHolder的使用可以减少inflate布局的次数,从而提高RecyclerView的性能。在onBindViewHolder()方法中,我们可以将数据绑定到ViewHolder中的视图组件上。
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.name.setText(mData.get(position).getName());
holder.age.setText(mData.get(position).getAge());
}
二、使用DiffUtil优化数据更新
RecyclerView经常需要更新数据,而DiffUtil可以提高数据更新的效率。DiffUtil是一个工具类,用于计算两个数据集之间的差异。在数据更新时,我们可以使用DiffUtil来计算数据集差异,从而只更新变化的部分,减少不必要的重绘和动画效果。
class MyDiffCallback extends DiffUtil.Callback {
private List oldList;
private List newList;
public MyDiffCallback(List oldList, List newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
MyData oldData = oldList.get(oldItemPosition);
MyData newData = newList.get(newItemPosition);
return oldData.getName().equals(newData.getName()) && oldData.getAge() == newData.getAge();
}
}
DiffUtil需要实现四个回调方法,getOldListSize()和getNewListSize()返回旧数据集和新数据集的大小,areItemsTheSame()判断两个数据是否为同一个item,areContentsTheSame()判断同一位置的两条数据是否内容相同。
在数据更新时,我们需要在新数据集合成前使用DiffUtil计算差异,将差异应用到适配器中并更新RecyclerView。
MyDiffCallback diffCallback = new MyDiffCallback(mData, newData); DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback); mData = newData; diffResult.dispatchUpdatesTo(this);
三、使用ItemDecoration美化界面和提升性能
ItemDecoration可以为RecyclerView添加自定义的分割线、颜色、边距等,使界面更加美观,同时也可以提高RecyclerView的性能。我们通常使用RecyclerView.ItemDecoration来创建ItemDecoration。
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private int mDividerHeight;
private Paint mPaint;
public MyItemDecoration(int dividerHeight, int dividerColor) {
mDividerHeight = dividerHeight;
mPaint = new Paint();
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.bottom = mDividerHeight;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < parent.getChildCount() - 1; i++) {
View child = parent.getChildAt(i);
float top = child.getBottom();
canvas.drawRect(left, top, right, top + mDividerHeight, mPaint);
}
}
}
在RecyclerView中添加ItemDecoration。
MyItemDecoration itemDecoration = new MyItemDecoration(dp2px(1), Color.GRAY); recyclerView.addItemDecoration(itemDecoration);
四、使用RecyclerView滑动监听减少内存消耗
RecyclerView在滑动时,会大量的创建和销毁视图,如果在滑动过程中同时处理复杂的数据操作,会导致卡顿或者OOM。因此,我们可以在RecyclerView滑动时停止加载图片或者其他占用内存的操作,从而减少内存消耗,提高滑动性能。我们可以通过RecyclerView的addOnScrollListener()监听RecyclerView的滑动状态。
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
//滑动停止,可以执行数据加载等其他操作
break;
case RecyclerView.SCROLL_STATE_DRAGGING:
//手指触摸滑动中,应停止数据加载等流操作
break;
case RecyclerView.SCROLL_STATE_SETTLING:
//惯性滑动中,应停止数据加载等流操作
break;
}
}
});
五、使用LayoutManager优化布局
LayoutManager是RecyclerView中布局管理器的基类,可以用于控制RecyclerView中子View的布局方式。使用LayoutManager可以实现多种复杂的布局,并且可以优化RecyclerView的性能。下面介绍几种常见的LayoutManager。
1. LinearLayoutManager
LinearLayoutManager是RecyclerView默认的布局管理器,控制子View的排列方向,有三种排列方式:VERTICAL、HORIZONTAL、Horizontal.VERTICAL。
LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager);
2. GridLayoutManager
GridLayoutManager可以将子View排列成网格形式。可以通过GridLayoutManager的构造函数来控制列数。
GridLayoutManager layoutManager = new GridLayoutManager(this, 2); recyclerView.setLayoutManager(layoutManager);
3. StaggeredGridLayoutManager
StaggeredGridLayoutManager可以将子View排列成不规则的网格形式。可以通过StaggeredGridLayoutManager的构造函数来控制列数和方向。
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); recyclerView.setLayoutManager(layoutManager);
完整代码示例
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List mData;
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
initData();
mAdapter = new MyAdapter(mData);
recyclerView.setAdapter(mAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
MyItemDecoration itemDecoration = new MyItemDecoration(dp2px(1), Color.GRAY);
recyclerView.addItemDecoration(itemDecoration);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
//滑动停止,可以执行数据加载等其他操作
break;
case RecyclerView.SCROLL_STATE_DRAGGING:
//手指触摸滑动中,应停止数据加载等流操作
break;
case RecyclerView.SCROLL_STATE_SETTLING:
//惯性滑动中,应停止数据加载等流操作
break;
}
}
});
}
private void initData() {
mData = new ArrayList();
mData.add(new MyData(1, "张三", 18));
mData.add(new MyData(2, "李四", 20));
mData.add(new MyData(3, "王五", 22));
mData.add(new MyData(4, "赵六", 21));
}
public int dp2px(float dpValue) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
class MyAdapter extends RecyclerView.Adapter {
private List mData;
public MyAdapter(List data) {
mData = data;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
MyViewHolder viewHolder = new MyViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.name.setText(mData.get(position).getName());
holder.age.setText(mData.get(position).getAge());
}
@Override
public int getItemCount() {
return mData.size();
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView age;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
age = (TextView) view.findViewById(R.id.age);
}
}
class MyData {
private int id;
private String name;
private int age;
public MyData(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class MyItemDecoration extends RecyclerView.ItemDecoration {
private int mDividerHeight;
private Paint mPaint;
public MyItemDecoration(int dividerHeight, int dividerColor) {
mDividerHeight = dividerHeight;
mPaint = new Paint();
mPaint.setColor(dividerColor);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.bottom = mDividerHeight;
}
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
for (int i = 0; i < parent.getChildCount() - 1; i++) {
View child = parent.getChildAt(i);
float top = child.getBottom();
canvas.drawRect(left, top, right, top + mDividerHeight, mPaint);
}
}
}
class MyDiffCallback extends DiffUtil.Callback {
private List oldList;
private List newList;
public MyDiffCallback(List oldList, List newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).getId() == newList.get(newItemPosition).getId();
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
MyData oldData = oldList.get(oldItemPosition);
MyData newData = newList.get(newItemPosition);
return oldData.getName().equals(newData.getName()) && oldData.getAge() == newData.getAge();
}
}
}
原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/259389.html
微信扫一扫
支付宝扫一扫