为所有Recycler View适配器创建基础适配器

9
public abstract class BaseAdapters extends RecyclerView.Adapter<BaseAdapters.MyViewHolder> implements View.OnClickListener {

    protected Context parentContext;
    public int layout_id;
    protected List<?> dataList = new ArrayList<>();


    public class MyViewHolder extends RecyclerView.ViewHolder  {

         MyViewHolder(View view) {
            super(view);
            declareViews(view,this);
        }
    }

    @Override
    public void onClick(View view) {
        onClickViews(view);
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
        bindView(holder, i);
    }

    public void notifyList(List<?> filterdNames) {
        this.dataList = filterdNames;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        if (dataList.size() == 0)
            return 5;
        else
            return dataList.size();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(layout_id, parent, false);
        return new MyViewHolder(itemView);
    }

    public abstract MyViewHolder bindView(MyViewHolder holder, int position);

    public abstract void onClickViews(View view);

    public abstract void declareViews(View view,MyViewHolder holder);

}

如何在扩展了 holder 的子类中执行每个项目选定的单击事件。


“every item selection” 是指在整个行上选择还是只是点击某个列表项组件? - Khemraj Sharma
在特定行项目上选择每个项目或设置值。 - PRATEEK BHARDWAJ
在子类中重写bindView方法设置点击事件,会有什么问题吗? - Khemraj Sharma
我认为我没有遇到这个问题,但是通过查看GitHub上的这些通用适配器,您将获得许多想法。 - Khemraj Sharma
你应该尝试这个 https://github.com/manojbhadane/GenericAdapter/ - Manoj Bhadane
6个回答

9
    import android.app.Activity;
    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;

    import java.util.ArrayList;
    import java.util.List;

    public abstract class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.MyViewHolder> {

        public int layout_id;
        protected List<?> dataList = new ArrayList<>();
        Context BASE_CONTEXT;
        public View itemview;

        public BaseAdapter(Context context) {
            this.BASE_CONTEXT = context;
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View view = LayoutInflater.from(viewGroup.getContext()).inflate(layout_id, viewGroup, false);
            return new MyViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder viewHolder, int position) {
            onBindViewHold(position, dataList.get(position));
        }

        public abstract View getView(View view);

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


        public abstract void onBindViewHold(int position, Object itemView);

        class MyViewHolder extends RecyclerView.ViewHolder {


            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                itemview = itemView;
                getView(itemView);
            }

        }

        public <T extends View> T bind(int id) {
            return itemview.findViewById(id);
        }


    }

public class Adapter extends BaseAdapter {

    TextView tv;

    Adapter(Context context, ArrayList<String> arrayList){
      super(context);
      dataList=arrayList;
      layout_id=R.layout.content_main2;

    }


    @Override
    public View getView(View view) {
        tv = bind(R.id.tv);
        return view;
    }

    @Override
    public void onBindViewHold( final int position, Object itemView) {

        String text=(String) itemView;
        Log.e("tv",tv.toString());
        tv.setText(text);
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(BASE_CONTEXT, ""+position, Toast.LENGTH_SHORT).show();
            }
        });
    }




}

优化此方法@Override public int getItemCount() { return dataList == null ? 0 : dataList.size(); } - Abdeldjalil Elaaeieida
这个适配器存在重复利用viewholder的问题,所以我做了一些修改,请看下面的答案..感谢提供基本结构 @rupali - Moumit

2
您可以参考此示例适配器类,并根据您的要求进行编辑:
public class absadapter extends RecyclerView.Adapter<absadapter.exViewHolder> {

List<abs.Ex> exList;
Context context;




absadapter(List exList) {
    this.exList= exList;

}
public static class exViewHolder extends RecyclerView.ViewHolder{
    CardView cardView;
    TextView exname;
    ImageView exlogo;


    exViewHolder(View itemView){
        super(itemView);
        cardView= itemView.findViewById(R.id.cardView);
        exname= itemView.findViewById(R.id.ex_name);
        exlogo=itemView.findViewById(R.id.exlogo);



    }


}
@Override
public absadapter.exViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
    View viewthigh= LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_abslayout,parent,false);
    absadapter.exViewHolder evh=new absadapter.exViewHolder(viewthigh);
    return evh;


}


@Override
public void onBindViewHolder(final absadapter.exViewHolder holder, final int position){
    holder.exname.setText(exList.get(position).name);
    holder.exlogo.setImageResource(exList.get(position).logoId);
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (position == 0 ){
                v.getContext().startActivity(new Intent(v.getContext(), abdetails.class));

            }
            if (position == 1) {
                v.getContext().startActivity(new Intent(v.getContext(), declinecrunch.class));


            }
            if (position == 2) {
                v.getContext().startActivity(new Intent(v.getContext(), dumsidebend.class));


            }
        }
    });


}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView){
    super.onAttachedToRecyclerView(recyclerView);
}
@Override
public int getItemCount() {
    return  exList.size();
}

有关主类,请参阅以下内容:

public class abs extends AppCompatActivity {


RecyclerView recyclerView;
Context context;
private List<Ex> exlist;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_abs);

    recyclerView= findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    LinearLayoutManager layoutManager=new LinearLayoutManager(context);
    recyclerView.setLayoutManager(layoutManager);

    initializeData();
    initializeAdapter();


}


private void initializeData(){

    exlist=new ArrayList<>();
    exlist.add(new abs.Ex("Crunches",R.drawable.crunchesgif));
    exlist.add(new abs.Ex("Decline Crunch",R.drawable.declinecrunch));
    exlist.add(new abs.Ex("Dumbell Side Bends",R.drawable.dumbbellsidebend));
    exlist.add(new abs.Ex("Hanging Leg Raises",R.drawable.hanginglegraises));
    exlist.add(new abs.Ex("Incline Leg Raises",R.drawable.inclinelegraises));
    exlist.add(new abs.Ex("Kneeling Cable Crunch",R.drawable.cablecrunch));
    exlist.add(new abs.Ex("Legs Raises",R.drawable.legraises));
    exlist.add(new abs.Ex("Flat Bench Lying Leg Raises",R.drawable.flatbenchlyinglegraise));
    exlist.add(new abs.Ex("Seated Jack Knife",R.drawable.seatedjackknife));
    exlist.add(new abs.Ex("Twisting Hip Raise",R.drawable.twistinghipraise));
    exlist.add(new abs.Ex("Weighted Crunch",R.drawable.weightedcrunch));
    exlist.add(new abs.Ex("Plank",R.drawable.plank));
    exlist.add(new abs.Ex("Side Plank",R.drawable.sideplank));
    exlist.add(new abs.Ex("Superman",R.drawable.superman));
    exlist.add(new abs.Ex("Twist Crunch",R.drawable.twistcrunch));


}
public void initializeAdapter(){
    absadapter rvadapter=new absadapter(exlist);
    recyclerView.setAdapter(rvadapter);
}
class Ex{
    String name;
    int logoId;

    Ex(String name,int logoId){
        this.name=name;
        this.logoId=logoId;
    }

}

公共类absadapter扩展自BaseAdapters {},我想在absadapter中访问holder。 - PRATEEK BHARDWAJ
如果您想处理点击事件,可以在bindviewholder()方法中实现。 - user10169672
BindView已在父类中定义,我想在子类中访问它。 - PRATEEK BHARDWAJ
你可以尝试使用ButterKnife库,参考链接:https://github.com/JakeWharton/butterknife - user10169672
如果需要创建具有多个视图类型的RecyclerView,可以按照以下步骤操作:
  1. 首先,在RecyclerView.Adapter中覆盖getItemViewType方法,并根据需要返回不同的视图类型。
  2. 然后,在onCreateViewHolder方法中,使用viewType参数来确定要创建哪种类型的视图。
  3. 最后,在onBindViewHolder方法中,根据viewType参数绑定正确的数据和视图。
这样就可以创建一个具有多个视图类型的RecyclerView了。
- Rohit Singh

2

这是 rupali 答案的扩展版本,我在滚动项目时发现了 recycle-view viewholder 的回收问题。因此,如果需要,您可以使用下面的代码:

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;


public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter<BaseRecyclerViewAdapter.BaseViewHolder> {

    public int layout_id;
    protected List<?> dataList = new ArrayList<>();
    protected BaseActivity Context;



    public BaseRecyclerViewAdapter(BaseActivity context) {
        this.Context = context;
    }

       @NonNull
    @Override
    public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(layout_id, viewGroup, false);
        return new BaseViewHolder(view);
    }


    @Override
    public void onBindViewHolder(@NonNull BaseViewHolder viewHolder, int position) {
        onViewHolderBind(viewHolder,position, dataList.get(position));
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    public abstract void onViewHolderBind(BaseViewHolder viewHolder, int position, Object data);

   public class BaseViewHolder extends RecyclerView.ViewHolder {
        public BaseViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }
}

用途

public class LicenseListAdapter extends BaseRecyclerViewAdapter {


    public LicenseListAdapter(BaseActivity appLicensePlanActivity, List<LicenseRatePlanResponse> licenseRatePlanResponseData) {
        super(appLicensePlanActivity);
        dataList = licenseRatePlanResponseData;
        layout_id = R.layout.item_list_license_plan;
    }


    @Override
    public void onViewHolderBind(BaseViewHolder viewHolder, int position, Object data) {
        Button btnBuyButtonOfLicencePlaneILLP;
        TextView lblAmountOfLicencePlaneILLP, lblDayOfLicencePlaneILLP;

        lblAmountOfLicencePlaneILLP = viewHolder.itemView.findViewById(R.id.lblAmountOfLicencePlaneILLP);
        lblDayOfLicencePlaneILLP = viewHolder.itemView.findViewById(R.id.lblDayOfLicencePlaneILLP);
        btnBuyButtonOfLicencePlaneILLP = viewHolder.itemView.findViewById(R.id.btnBuyButtonOfLicencePlaneILLP);

        final LicenseRatePlanResponse tempLicensePlan = (LicenseRatePlanResponse) data;

        lblAmountOfLicencePlaneILLP.setText(KSUtility.GetFloatWithOutPrecesion(tempLicensePlan.getAmount()).toString() +" only");
        lblDayOfLicencePlaneILLP.setText(tempLicensePlan.getValidityDays().toString() +" days");
        btnBuyButtonOfLicencePlaneILLP.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                PaymentHelper.OpenPaymentDialog(Context, TransactionType.LicenseRenew, tempLicensePlan.getAmount(),tempLicensePlan.getLicenseRatePlanId());
            }
        });
    }
}

这里有一个问题,我们在每个绑定上都要再次执行findViewById。 - gpl

1
在“BaseAdapters”的子类中覆盖处理点击事件的方法应该可以解决问题(根据您在其他帖子中的评论,我认为bindView()处理点击事件;覆盖任何您知道处理点击事件的方法即可):
class new_adapter extends BaseAdapters{
    //...
    @Override
    public MyViewHolder bindView(MyViewHolder holder, int position){
        //you could alter how click events are handled here.
    }
    //...
}

1

有许多方法可供选择,其中之一是使用Java泛型

在您的onCreateViewHolder中设置点击事件,设置点击并传递所点击行的列表项或任何您需要的内容。如果需要位置或任何其他字段,可以自定义onClickViews方法。

@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
    ..
    itemView.setOnClickListener(v -> onClickViews(itemView, dataList.get(position)));
    ..
}

并且

public abstract void onClickViews(View view, T object);

使用方法如下:
public class SampleAdapter extends BaseAdapters<Item> {

    @Override
    public int getRowLayout() {
        return R.layout.row;
    }

    @Override
    public void onClickViews(View view, Item object) {
        // row clicked   
    }
}

我稍微编辑了你的类。

public abstract class BaseAdapters<T> extends RecyclerView.Adapter<BaseAdapters.MyViewHolder> {

    protected List<T> dataList = new ArrayList<>();

    public class MyViewHolder extends RecyclerView.ViewHolder {
        MyViewHolder(View view) {
            super(view);
            declareViews(view, this);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
        bindView(holder, i);
    }

    public void notifyList(List<T> filteredNames) {
        dataList = filteredNames;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(getRowLayout(), parent, false);
        itemView.setOnClickListener(v -> onClickViews(itemView, dataList.get(position)));
        return new MyViewHolder(itemView);
    }

    public abstract @LayoutRes
    int getRowLayout();

    public abstract MyViewHolder bindView(MyViewHolder holder, int position);

    public abstract void onClickViews(View view, T object);

    public abstract void declareViews(View view, MyViewHolder holder);
}

0

基础的 Recycler 适配器将会是这样的

public class BaseRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int BOTTOM_VIEW_TYPE = 3;

private List<Object> listModels;
private Context mContext;
private OnItemClickListener onClickListener = null;

public BaseRecyclerViewAdapter(Context context) {
    this.mContext = context;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view;
    switch (viewType) {
    case BOTTOM_VIEW_TYPE:
            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_bottomview_type, parent, false);
            return new ChildViewHolder(view);
    }
    return null;
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    final Object model = listModels.get(position);
    if (model != null && model.getId() > 0) {
        ((BaseViewHolder) holder).bind(model, position);
    } else if (model != null) {
        ((TopViewViewHolder) holder).bind(model, position);
    }
}

@Override
public int getItemViewType(int position) {
    if (listModels.get(position).getId() > 0) {
        return BASE_VIEW_TYPE;
    } else {
        return TOP_VIEW_TYPE;
    }
}

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


public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
    this.onClickListener = onItemClickListener;
}
private class ChildViewHolder extends RecyclerView.ViewHolder {
    TextView tv_bottomName;

    BottomViewHolder(View v) {
        super(v);
        tv_bottomName = v.findViewById(R.id.tv_bottomName);
    }

    void bind(Object object, final int position) {
        tv_bottomName.setOnClickListener(view -> onClickListener.onItemClick(object, tv_bottomName, position));

    }
}

}

并使用自定义接口来处理 OnItemClickListner

 public interface OnItemClickListener {
void onItemClick(Object object, View view, int position);}

在活动或片段中实现监听器。

我不想在子类中创建holder。我已经在基类中创建了通用的holder,它将包含适配器设置为每个布局的引用。 - PRATEEK BHARDWAJ
好的,那么您可以在每个子类中使用接口执行onclick监听器。 - gStephin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接