RecyclerView的刷新分為以下兩種情況:
- 刷新的數(shù)據(jù)量比較大或者刷新Item的位置不確定
- .刷新指定Item
1.如果大量的數(shù)據(jù)被修改或者被修改數(shù)據(jù)的位置不確定桶良,則使用
adapter.notifyDataSetChanged();
這個方法很消耗性能苞也,不到萬不得已不要使用勺疼,請盡量使用下面的刷新方法揽祥。
2.刷新某一項(常用)
//刷新某Item中的所有組件
adapter.notifyItemChanged(position);
//刷新某Item中的部分組件
adapter.notifyItemChanged(position, payloads);
//插入Item
adapter.notifyItemInserted(position);
//刪除Item
adapter.notifyItemRemoved(position);
//移動Item
adapter.notifyItemMoved(position, position + 1);
需求1:點(diǎn)擊按鈕1堡牡,使圖片和文字改變煤伟。
switch (view.getId()){
case R.id.image:
Toast.makeText(MainActivity.this, "點(diǎn)擊了圖片", Toast.LENGTH_SHORT).show();
break;
case R.id.button_1:
Toast.makeText(MainActivity.this, "點(diǎn)擊了按鈕1", Toast.LENGTH_SHORT).show();
PhotoBean photoBean = list.get(position);
photoBean.setName("修改恐似!");
photoBean.setUrl("http://pic29.nipic.com/20130511/9252150_174018365301_2.jpg");
adapter.notifyItemChanged(position);
break;
case R.id.button_2:
Toast.makeText(MainActivity.this, "點(diǎn)擊了按鈕2", Toast.LENGTH_SHORT).show();
break;
}
需求2:點(diǎn)擊按鈕2,使按鈕2高亮涣旨。
首先添加一個clickButton狀態(tài)
public class PhotoBean {
private String name;
private String url;
private byte clickButton;//0:點(diǎn)擊了圖片歪架,1:點(diǎn)擊了按鈕1,2:點(diǎn)擊了按鈕2
public PhotoBean(){}
public PhotoBean(String url, String name, byte clickButton){
this.url = url;
this.name = name;
this.clickButton = clickButton;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public byte getClickButton() {
return clickButton;
}
public void setClickButton(byte clickButton) {
this.clickButton = clickButton;
}
}
修改onBindViewHolder方法,將按鈕變黃
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
PhotoBean dataListBean = mData.get(position);
if(dataListBean != null){
Glide.with(mContext).load(dataListBean.getUrl()).into(((ViewHolder)holder).imgView);
((ViewHolder)holder).tvName.setText(dataListBean.getName());
if(dataListBean.getClickButton() == 2){
((ViewHolder)holder).button_2.setBackgroundColor(Color.YELLOW);
}
}
((ViewHolder)holder).imgView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickLitener != null) {
if(mData != null && mData.size() > 0){
mOnItemClickLitener.onItemClick(((ViewHolder)holder).imgView, position);
}
}
}
});
((ViewHolder)holder).button_1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickLitener != null) {
if(mData != null && mData.size() > 0){
mOnItemClickLitener.onItemClick(((ViewHolder)holder).button_1, position);
}
}
}
});
((ViewHolder)holder).button_2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mOnItemClickLitener != null) {
if(mData != null && mData.size() > 0){
mOnItemClickLitener.onItemClick(((ViewHolder)holder).button_2, position);
}
}
}
});
}
效果如下:
這樣貌似已經(jīng)實(shí)現(xiàn)了功能霹陡,但是存在兩個嚴(yán)重的弊端:
1.我只要將按鈕2改變顏色就行了和蚪,為什么圖片還會刷新?
2.我每次點(diǎn)擊按鈕2烹棉,圖片攒霹、文字、按鈕都要重新排版一次浆洗,嚴(yán)重消耗性能催束,也許現(xiàn)在手機(jī)性能比較好,很多人不在乎伏社,但是我在乎抠刺。
解決方案:使用payloads實(shí)現(xiàn)刷新Item中的部分控件。
修改按鈕2點(diǎn)擊事件實(shí)現(xiàn)
case R.id.button_2:
Toast.makeText(MainActivity.this, "點(diǎn)擊了按鈕2", Toast.LENGTH_SHORT).show();
PhotoBean photoBean2 = new PhotoBean();
photoBean2.setClickButton((byte) 2);
adapter.notifyItemChanged(position, photoBean2);
break;
添加回調(diào)方法
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
if(payloads != null && !payloads.isEmpty()){
if(payloads.get(0) instanceof PhotoBean){
PhotoBean photoBean = (PhotoBean) payloads.get(0);
if(photoBean.getClickButton() == 2){
((ViewHolder)holder).button_2.setBackgroundColor(Color.YELLOW);
}
}
}else{
onBindViewHolder(holder, position);
}
}
展示效果
需求3:實(shí)現(xiàn)添加刪除和移動功能
case R.id.button_3:
Toast.makeText(MainActivity.this, "添加Item", Toast.LENGTH_SHORT).show();
list.add(position, new PhotoBean(list.get(position).getUrl(), list.get(position).getName(), list.get(position).getClickButton()));
adapter.notifyItemInserted(position);
break;
case R.id.button_4:
Toast.makeText(MainActivity.this, "刪除Item", Toast.LENGTH_SHORT).show();
list.remove(position);
adapter.notifyItemRemoved(position);
break;
case R.id.button_5:
Toast.makeText(MainActivity.this, "移動Item", Toast.LENGTH_SHORT).show();
Collections.swap(list,position,position+1);// 元素互換
adapter.notifyItemMoved(position, position + 1);
break;
添加效果:
刪除效果:
移動效果:
另外洛口,以上講解的都是刷新一個Item矫付, 下面四個方法是更新多個Item
public final void notifyItemRangeChanged(int positionStart, int itemCount);
public final void notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload)第焰;
public final void notifyItemRangeInserted(int positionStart, int itemCount)买优;
public final void notifyItemRangeRemoved(int positionStart, int itemCount) ;
其實(shí),更新一個Item的方法杀赢,底層都會調(diào)用以上四個方法的其中一個烘跺,只是此時itemCount=1。
需要注意的是:
mRecyclerView.setHasFixedSize(false);
您可能還需要知道setHasFixedSize的的使用脂崔。
- 當(dāng)setHasFixedSize為true時滤淳,Item高度變化時,不會重新計算高度砌左;
- 當(dāng)setHasFixedSize為false時脖咐,Item高度變化時,會重新計算高度汇歹;
setHasFixedSize默認(rèn)是false屁擅。
當(dāng)執(zhí)行
onItemRangeChanged()
onItemRangeInserted()
onItemRangeRemoved()
onItemRangeMoved()
時,可以設(shè)置setHasFixedSize為true产弹,讓Item的高度不會重新計算派歌,這樣可以保證性能。
如果調(diào)用了notifyDataSetChanged痰哨,Item的大小總是會被重新計算胶果。
大家可以參考一下文章:
RecyclerView性能優(yōu)化:setHasFixedSize
[本章完...]