1.寫一個基類viewHolder
public static class OptionBaseViewHolder<T,B extends ViewBinding> extends RecyclerView.ViewHolder implements View.OnClickListener {
public B binding;
OptionListAdapter adapter;
T data;
Context context;
//構造參數傳入 binding和adapter,傳adapter可以方便獲取adpter內部方法和上下文
public OptionBaseViewHolder(@NonNull B binding ,OptionListAdapter adapter) {
super(binding.getRoot());
this.binding = binding;
this.adapter =adapter;
this.context = adapter.context;
}
protected void dataBindView(T data){this.data = data;}
@Override
public void onClick(View v){};
}
2.寫一個繼承基類的自定義ViewHolder 泛型傳入<資料類型,Item的ViewBinding>
public static class WeekItemViewHolder extends OptionBaseViewHolder<String, ItemTimerWeekBinding>{
public static ItemCallback<String> listener;//static listener記得在不需要用到時使listener=null
public WeekItemViewHolder(@NonNull ItemTimerWeekBinding binding, OptionListAdapter adapter) {
super(binding, adapter);
binding.item.setOnClickListener(this);
}
@Override
protected void dataBindView(String data) {
super.dataBindView(data);
binding.itemName.setText(data);
}
@Override
public void onClick(View v) {
super.onClick(v);
if(v == binding.item){
if(listener!=null)listener.onClickItem(data);
}
}
}
public static abstract class ItemCallback<T>{
public void onClickItem(T data){};
}
3.寫一個共通的Adapter
public class OptionListAdapter extends RecyclerView.Adapter<OptionListAdapter.OptionBaseViewHolder> {
protected ArrayList<Object> dataList; //資料源
protected Context context;
private Class<? extends ViewBinding> viewBindingClazz ;
private Class<? extends OptionBaseViewHolder> viewHolderClazz;
//構造參數傳入上下文,dataList,自定義ViewHolder.class
public OptionListAdapter(Context context , ArrayList<Object> dataList, Class<? extends OptionBaseViewHolder> viewHolderClazz){
this.context = context;
this.dataList = dataList;
this.viewHolderClazz = viewHolderClazz;
this.viewBindingClazz = getViewBindingClass(viewHolderClazz);
}
//透過viewHolder泛型參數的取得ViewBinding的Class
private Class getViewBindingClass(Class<? extends OptionBaseViewHolder> viewHolderClazz){
ParameterizedType parameterizedType = (ParameterizedType) viewHolderClazz.getGenericSuperclass();
Type viewBindingActualTypeArgument = parameterizedType.getActualTypeArguments()[1];
return (Class<? extends ViewBinding>)viewBindingActualTypeArgument;
}
//透過反射動態生成viewHolder
@NonNull
@Override
public OptionListAdapter.OptionBaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
try {
Method inflateMethod = viewBindingClazz.getMethod("inflate", LayoutInflater.class, ViewGroup.class, boolean.class);
ViewBinding binding = (ViewBinding) inflateMethod.invoke(null, LayoutInflater.from(context), parent, false);
Constructor<?> constructor = Constructor<?> constructor = viewHolderClazz.getConstructor(viewBindingClazz,this.getClass());
OptionListAdapter.OptionBaseViewHolder viewHolder = (OptionListAdapter.OptionBaseViewHolder) constructor.newInstance(binding,this);
return viewHolder;
} catch (Exception e) {
}
return null;
}
//傳入資料源
@Override
public void onBindViewHolder(@NonNull OptionListAdapter.OptionBaseViewHolder holder, int position) {
holder.dataBindView(dataList.get(position));
}
@Override
public int getItemCount() {
return dataList.size();
}
}
4.Activity調用運行:
public void initRecycleView(){
ArrayList<String> options= new ArrayList<>();
options.add("選項1");
options.add("選項2");
options.add("選項3");
OptionListAdapter adapter = new OptionListAdapter(this,options,
WeekItemViewHolder.class);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
binding.testRecyclerview.setLayoutManager(linearLayoutManager);
binding.testRecyclerview.setAdapter(adapter)
WeekItemViewHolder.listener = new ItemCallback<String>() {
@Override
public void onClickItem(String data) {
super.onClickItem(data);
Log.d("test","點擊了---"+data)
}
};
}
5.Activity銷毀注意:
@Override
public void onDestroy() {
super.onDestroy();
WeekItemViewHolder.listener = null;
}
6.其實後來實際用一用發現listener還是不要用static比較好 ,建議大家把listener從Adapter的構造參數傳入,用反射傳進去viewHolder,不然一直在onDestroy設null手好痠好麻煩,而且在忘記設的時候,可能有無法預期的內存洩漏導致閃退。