RecyclerView notifyItemInserted 复制了之前条目的数据
RecyclerView notifyItemInserted duplicates previous entry's data
所以出于某种原因,每当我向我的 ArrayList 添加一个新项目并通知 recyclerview 它已被添加时,它会复制前一个条目的数据。因此创建了视图,但使用的是最后一个条目中的数据而不是当前数据。
奇怪的是我使用 ORM Sugar 保存项目,所以当我检索它们时会显示正确的数据。这表明正在添加数据,但视图未正确显示。
我只能假设每当我使用 notifyItemInserted 方法时,recyclerview 都不会调用 onBindViewHolder,因为当我使用 notifyDataSetChange()
时会显示正确的数据
这是我添加新项目的方法
@Override
public void AddCalorieToHistoryList(int calorieAmount, int currentCalorieAmount) {
// Get the date and the calorie amount from what the user entered.
Date date = new Date();
// Create the calorie history item and then save it (via ORM Sugar Library)
CalorieHistory calorieHistory = new CalorieHistory(date.toString(), calorieAmount);
calorieHistory.save();
// Notify the view of the new item that should be inserted.
historyView.InsertNewListItem(calorieHistory);
SubtractFromCurrentCalorieAmount(calorieAmount, currentCalorieAmount);
}
historyView 的方法
@Override
public void InsertNewListItem(CalorieHistory calorieHistoryItem) {
// Add the new item
calorieHistories.add(calorieHistoryItem);
// Notify the insert so we get the animation from the default animator
historyListAdapter.notifyItemInserted(0);
}
这是 recyclerview 适配器
public class HistoryListAdapter extends RecyclerView.Adapter<HistoryListAdapter.HistoryListViewHolder> {
List<CalorieHistory> calorieHistoryList;
public HistoryListAdapter(List<CalorieHistory> historyList) {
this.calorieHistoryList = historyList;
}
// I think this is run once, it generates the view holder from the layout that we are using for each list item.
// This way it won't have to grab it each time we make a new list item. It's all stored on our view holder.
@Override
public HistoryListViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.calorie_history_item, parent, false);
return new HistoryListViewHolder(itemView);
}
// This executes everytime we make a new list item, it binds the data to the view.
@Override
public void onBindViewHolder(HistoryListViewHolder holder, int position) {
// Get the current calorHistory object and set it's data to the views.
CalorieHistory calorieHistory = calorieHistoryList.get(position);
holder.tvDate.setText(calorieHistory.date);
holder.tvAmount.setText(String.valueOf(calorieHistory.numberOfCalories));
}
@Override
public int getItemCount() {
// Return the size of our array.
return calorieHistoryList.size();
}
public static class HistoryListViewHolder extends RecyclerView.ViewHolder {
public TextView tvDate;
public TextView tvAmount;
public HistoryListViewHolder(View v) {
super(v);
tvDate = (TextView) v.findViewById(R.id.calorie_date);
tvAmount = (TextView) v.findViewById(R.id.calorie_amount);
}
}
}
根据列表规范,List.add(E object)
应将项目添加到列表的 END。您似乎在向 END 添加项目,同时在第一个项目上通知插入。
为了将项目添加为第一项,您应该更改
calorieHistories.add(calorieHistoryItem);
到
calorieHistories.add(0, calorieHistoryItem);
编辑
或者,如果您确实要将项目添加到 END,则应更改
historyListAdapter.notifyItemInserted(0);
到
historyListAdapter.notifyItemInserted(calorieHistories.size()-1);
所以出于某种原因,每当我向我的 ArrayList 添加一个新项目并通知 recyclerview 它已被添加时,它会复制前一个条目的数据。因此创建了视图,但使用的是最后一个条目中的数据而不是当前数据。
奇怪的是我使用 ORM Sugar 保存项目,所以当我检索它们时会显示正确的数据。这表明正在添加数据,但视图未正确显示。
我只能假设每当我使用 notifyItemInserted 方法时,recyclerview 都不会调用 onBindViewHolder,因为当我使用 notifyDataSetChange()
时会显示正确的数据这是我添加新项目的方法
@Override
public void AddCalorieToHistoryList(int calorieAmount, int currentCalorieAmount) {
// Get the date and the calorie amount from what the user entered.
Date date = new Date();
// Create the calorie history item and then save it (via ORM Sugar Library)
CalorieHistory calorieHistory = new CalorieHistory(date.toString(), calorieAmount);
calorieHistory.save();
// Notify the view of the new item that should be inserted.
historyView.InsertNewListItem(calorieHistory);
SubtractFromCurrentCalorieAmount(calorieAmount, currentCalorieAmount);
}
historyView 的方法
@Override
public void InsertNewListItem(CalorieHistory calorieHistoryItem) {
// Add the new item
calorieHistories.add(calorieHistoryItem);
// Notify the insert so we get the animation from the default animator
historyListAdapter.notifyItemInserted(0);
}
这是 recyclerview 适配器
public class HistoryListAdapter extends RecyclerView.Adapter<HistoryListAdapter.HistoryListViewHolder> {
List<CalorieHistory> calorieHistoryList;
public HistoryListAdapter(List<CalorieHistory> historyList) {
this.calorieHistoryList = historyList;
}
// I think this is run once, it generates the view holder from the layout that we are using for each list item.
// This way it won't have to grab it each time we make a new list item. It's all stored on our view holder.
@Override
public HistoryListViewHolder onCreateViewHolder(ViewGroup parent, int i) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.calorie_history_item, parent, false);
return new HistoryListViewHolder(itemView);
}
// This executes everytime we make a new list item, it binds the data to the view.
@Override
public void onBindViewHolder(HistoryListViewHolder holder, int position) {
// Get the current calorHistory object and set it's data to the views.
CalorieHistory calorieHistory = calorieHistoryList.get(position);
holder.tvDate.setText(calorieHistory.date);
holder.tvAmount.setText(String.valueOf(calorieHistory.numberOfCalories));
}
@Override
public int getItemCount() {
// Return the size of our array.
return calorieHistoryList.size();
}
public static class HistoryListViewHolder extends RecyclerView.ViewHolder {
public TextView tvDate;
public TextView tvAmount;
public HistoryListViewHolder(View v) {
super(v);
tvDate = (TextView) v.findViewById(R.id.calorie_date);
tvAmount = (TextView) v.findViewById(R.id.calorie_amount);
}
}
}
根据列表规范,List.add(E object)
应将项目添加到列表的 END。您似乎在向 END 添加项目,同时在第一个项目上通知插入。
为了将项目添加为第一项,您应该更改
calorieHistories.add(calorieHistoryItem);
到
calorieHistories.add(0, calorieHistoryItem);
编辑
或者,如果您确实要将项目添加到 END,则应更改
historyListAdapter.notifyItemInserted(0);
到
historyListAdapter.notifyItemInserted(calorieHistories.size()-1);