在适配器类的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();
        }
    });
}


}

android - Android RecyclerView:在notifyDataSetChanged之后更新所有项目的高度-LMLPHP
当前,屏幕上仅可见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/

10-11 00:35