在适配器类的onCreateViewHolder
中,我将屏幕的总体高度分布在我拥有的项目上,如下所示:
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_card, parent, false);
// float weight = 1 / (mCards.size() * 1.0f);
// LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0, weight);
// view.setMinimumHeight(params.height);
int height = parent.getMeasuredHeight() / mCards.size();
view.setMinimumHeight(height - 15);
return new ViewHolder(view, listener);
}
但是,当我呼叫
adapter.notifyDataSetChanged()
时,只有新项目才获得新高度。所有其他(已经存在)的项目都保持旧高度。更新数据集时,应该将高度计算移动到哪里以进行检查?
最佳答案
在RecyclerView中,当创建新的视图对象并将其附加到父对象时,将调用onCreateViewHolder(),在滚动时视图离开屏幕且屏幕上出现新视图时,将调用onBindViewHolder()。
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder>{
private Context context;
private ArrayList<String> months = new ArrayList<>();
public RecyclerAdapter(Context context, ArrayList<String> months){
this.context = context;
this.months = months;
}
@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View vi = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
Log.d("RECYCLER_CALLBACKS", "onCreateViewHolder() " + parent.getChildCount());
return new ViewHolder(vi);
}
@Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
holder.month.setText(months.get(position));
Log.d("RECYCLER_CALLBACKS", "onBindViewHolder() " + months.get(holder.getAdapterPosition()));
}
@Override
public void onViewRecycled(ViewHolder holder) {
super.onViewRecycled(holder);
Log.d("RECYCLER_CALLBACKS", "onViewRecycled() " + months.get(holder.getAdapterPosition()));
}
@Override
public int getItemCount() {
return months.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardView;
private TextView month;
private TextView date;
public ViewHolder(View itemView) {
super(itemView);
cardView = (CardView) itemView.findViewById(R.id.cardView);
month = (TextView) itemView.findViewById(R.id.textView2);
date = (TextView) itemView.findViewById(R.id.textView3);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button;
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private RecyclerAdapter adapter;
private static int MONTH_COUNT = 1;
private ArrayList<String> monthsList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
monthsList.add("January");
monthsList.add("February");
monthsList.add("March");
monthsList.add("April");
monthsList.add("May");
monthsList.add("June");
monthsList.add("July");
monthsList.add("August");
monthsList.add("September");
monthsList.add("October");
monthsList.add("November");
monthsList.add("December");
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter(this, monthsList);
recyclerView.setAdapter(adapter);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
monthsList.add("New Month " + MONTH_COUNT);
MONTH_COUNT++;
adapter.notifyDataSetChanged();
}
});
}
}
当前,屏幕上仅可见6个项目。应用启动后
08-26 21:32:23.547 28518-28518 / com.stabstudio.afteranimation D / RECYCLER_CALLBACKS:onCreateViewHolder()0
08-26 21:32:23.557 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()1
08-26 21:32:23.557 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()2月
08-26 21:32:23.563 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()2
08-26 21:32:23.563 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()3月
08-26 21:32:23.569 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()3
08-26 21:32:23.569 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()四月
08-26 21:32:23.575 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()4
08-26 21:32:23.575 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()可能
08-26 21:32:23.581 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()5
08-26 21:32:23.581 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()六月
最初,随着视图的创建,将为每个视图调用onCreateViewHolder()和onBindViewHolder()。当我们向下滚动到底部时
08-26 21:37:36.579 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onCreateViewHolder()6
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()7月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onCreateViewHolder()7
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()8月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onCreateViewHolder()7
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()9月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onCreateViewHolder()7
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()十月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onViewRecycled()一月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()十一月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onViewRecycled()2月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onBindViewHolder()十二月
28518-28518 / com.stabstudio.animation D / RECYCLER_CALLBACKS:
onViewRecycled()3月
因此,onCreateViewHolder()在第8个视图之后停止被调用,而是调用了onViewRecycled(),它使用离开屏幕的同一视图而不是创建新的View。
现在,当我们滚动回到顶部时:
08-26 21:54:20.262 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()3月
08-26 21:54:20.784 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()十二月
08-26 21:54:21.471 28518-28518 / com.stabstudio.after动画
D / RECYCLER_CALLBACKS:onBindViewHolder()2月
08-26 21:54:21.835 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()十一月
08-26 21:54:22.277 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()一月
08-26 21:54:26.050 28518-28518 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()十月
当我们向上滚动时,12月首先离开屏幕,3月进入屏幕。所以,
12月被回收,以利用回调将其保留到3月
onViewRecycled()12月和onBindViewHolder()3月。
同样,11月被回收,2月取代
十一月的onViewRecycled()和onBindViewHolder()的回调
二月。
最后是十月的onViewRecycled()和一月的onBindViewHolder()。
现在,当我们创建新的Month时,我们调用notifyDataSetChanged()将更改报告给适配器:
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onViewRecycled()5 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()4
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onViewRecycled()3 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()-1
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onViewRecycled()-1 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()-1
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onViewRecycled()-1 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onViewRecycled()-1
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onViewRecycled()-1 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()7月
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onBindViewHolder()2597年2月2日/com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()9月
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onBindViewHolder()2597年2月2日/com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()十一月
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onCreateViewHolder()5 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()十二月
动画2597-2597 / com.stabstudio.after D / RECYCLER_CALLBACKS:
onCreateViewHolder()6 2597-2597 / com.stabstudio.afteranimation
D / RECYCLER_CALLBACKS:onBindViewHolder()新月1
调用notifyDataSetChanged()后,所有视图将被回收,并且onCreateViewHolder()会再次调用,其显示次数与屏幕上显示的项目数+ 2相同,在顶部为1,在底部为1(不是)可见。在这种情况下,无论RecyclerView中有多少项目,它都是8次。
因此,您应该将高度计算移动到所有视图都被调用的onBindViewHolder()而不是onCreateViewHolder(),后者仅被调用与屏幕上可见项目数相同的次数。
关于android - Android RecyclerView:在notifyDataSetChanged之后更新所有项目的高度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45884240/