如何将“ onCreateViewHolder”中的代码迁移到“ onBindViewHolder”

时间:2019-04-11 14:25:15

标签: android android-recyclerview recycler-adapter

这是我在 onCreateViewHolder

中的代码
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

  ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(R.layout.widget_holder, parent, false);
    if (CAT_IMAGE_IDS.get(i).getButton()) {
      LinearLayout ln = new LinearLayout(parent.getContext());
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(230, 250, Gravity.CENTER);
      ln.setLayoutParams(params);
      viewGroup.addView(ln);
      i++;
      return new ItemViewHolder(viewGroup);

    } else if (CAT_IMAGE_IDS.get(i).getDummy()) {

      LinearLayout ln = new LinearLayout(parent.getContext());
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(230, 250, Gravity.CENTER);
      ln.setLayoutParams(params);
      viewGroup.setVisibility(View.INVISIBLE);
      viewGroup.addView(ln);
      i++;
      return new ItemViewHolder(viewGroup);
}

有人告诉我在此处编写它不是一个好习惯,它应该放在 onBindViewHolder 中。

即使我在网上查看了一些示例,我似乎也无法弄清楚如何正确地做到这一点。

那我应该怎么做?

2 个答案:

答案 0 :(得分:0)

onCreateViewHolder()应该包含创建ViewHolder的代码,onBindViewHolder()应该用数据填充它。当您的集合中包含许多元素并由用户滚动时,任何其他方法都会引起问题。

据我所知,就您而言,无论CAT_IMAGE_IDS.get(i).getButton()CAT_IMAGE_IDS.get(i).getDummy()的值如何,创建的布局都不会不同。这意味着onBindViewHolder()的正文应如下所示:

ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(R.layout.widget_holder, parent, false);
LinearLayout ln = new LinearLayout(parent.getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(230, 250, Gravity.CENTER);
ln.setLayoutParams(params);
viewGroup.addView(ln);
return new ItemViewHolder(viewGroup);

请注意,我只留下了实际创建布局的代码,而不是设置可见性的部分-应该在onBindViewHolder()

内部完成
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    if (CAT_IMAGE_IDS.get(position).getButton()){
        holder.itemView.setVisibility(View.VISIBLE);
    } else if (CAT_IMAGE_IDS.get(position).getDummy()){
        holder.itemView.setVisibility(View.INVISIBLE);
    }
}

通常,onBindViewHolder()不仅可以改变元素的可见性,还可以做更多的事情,例如,用文本和图片填充视图。

您可以check the official guide以获取更多信息。

答案 1 :(得分:0)

这里遗漏的逻辑仅仅是利用View Holder方法并相应地回收您的视图。看看以下示例代码:

package yourpackage.goeshere;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import yourpackage.goeshere.R;

public class SampleRecyclerViewAdapter2  extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    //region Vars
    private List<Object> mListObjects;
    private LayoutInflater mInflater;
    private Context context;
    //endregion 

    //region Constructor
    public SampleRecyclerViewAdapter2(@NonNull Context context){
        this.context = context;
        this.mInflater = LayoutInflater.from(this.context);
    }

    //endregion

    //region Initialization
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.your_layout_file_here, parent, false);
        SampleRecyclerViewAdapter2.AdapterHolderType viewHolder2 = new SampleRecyclerViewAdapter2.AdapterHolderType(view);
        return viewHolder2;
    }
    //endregion

    //region Override Methods
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder0, final int position) {

        final Object nonCastObject = mListObjects.get(position);
        if(nonCastObject == null){
            //Decide what to do here
            return;
        }

        //Cast the Holder Here
        SampleRecyclerViewAdapter2.AdapterHolderType holder = (SampleRecyclerViewAdapter2.AdapterHolderType) holder0;

        //Cast the Object Here to your pojo
//      MyCustomObject obj = (MyCustomObject) nonCastObject;

        //Set Fields here; adjust dynamically from cast object
        holder.adapter_sample_recyclerview_iv.setImageResource(R.mipmap.ic_launcher);
        holder.adapter_sample_recyclerview_tv.setText("Some text");

        //Set listeners here
        holder.rootview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Can set a click listener here if need be
            }
        });

        //Handle animations here if you want them
    }

    @Override
    public int getItemCount() {
        return ((this.mListObjects == null) ? 0 : this.mListObjects.size());
    }

    //endregion

    //region Class Methods

    /**
     * Add one object to the list
     * @param position Position to add into
     * @param mObject Single object to update. If null, will be ignored (Call remove instead).
     *                {@link Object}
     */
    public void addOneObject(int position, Object mObject){
        if(mObject == null){
            return;
        }
        if(position < 0 || position > getItemCount()){
            //Out of bounds
            return;
        }
        if(this.mListObjects == null){
            this.mListObjects = new ArrayList<>();
        }
        this.mListObjects.add(position, mObject);
        this.notifyItemChanged(position);
    }

    /**
     * Update one object in the list
     * @param position Position to update
     * @param mObject Single object to update. If null, will be ignored (Call remove instead).
     *                {@link Object}
     */
    public void updateOneObject(int position, Object mObject){
        if(mObject == null){
            return;
        }
        if(position < 0 || position >= getItemCount()){
            //Out of bounds
            return;
        }
        this.mListObjects.set(position, mObject);
        this.notifyItemChanged(position);
    }

    /**
     * Remove a single object from the list
     * @param position Position to remove
     */
    public void removeOneObject(int position){
        if(this.mListObjects != null){
            if(position < 0 || position >= getItemCount()){
                this.mListObjects.remove(position);
                this.notifyItemChanged(position);
            }
        }
    }

    /**
     * Set data list
     * @param mListObjects {@link Object}
     */
    public void setListObjects(List<Object> mListObjects){
        this.mListObjects = mListObjects;
        this.notifyDataSetChanged();
    }
    //endregion

    //region Class Holders

    class AdapterHolderType extends RecyclerView.ViewHolder {

        ImageView adapter_sample_recyclerview_iv;
        RelativeLayout rootview;
        TextView adapter_sample_recyclerview_tv;

        public AdapterHolderType(View itemView) {
            super(itemView);
            this.adapter_sample_recyclerview_tv = itemView.findViewById(R.id.adapter_sample_recyclerview_tv);
            this.rootview = itemView.findViewById(R.id.rootview);
            this.adapter_sample_recyclerview_iv = itemView.findViewById(R.id.adapter_sample_recyclerview_iv);
        }
    }

    //endregion
}

在其中,holder类用作到UI的直接链接,可以通过将holder强制转换为您指定的类型来调用。

强制转换后,您可以使用对象设置值来执行所需的操作。

在此示例代码中,我使用了通用的Object,但您应该使用在类中使用的任何对象