Как избавиться от дубликатов RecyclerView Adapter? - PullRequest
0 голосов
/ 21 октября 2018

У меня есть универсальный Adapter со всеми состояниями.Я использую это везде.Но этот класс очень громоздок и не соответствует принципам DRY

public class AdapterWithStates extends RecyclerView.Adapter {

    private static final int STATE_NORMAL = 0;
    public static final int STATE_LOADING = 1;
    public static final int STATE_EMPTY = 3;
    public static final int STATE_ERROR = 4;
    public static final int STATE_ERROR_CONNECTION = 5;

    private static final int TYPE_NORMAL = 1000;
    private static final int TYPE_LOADING = 1001;
    private static final int TYPE_LOADING_MORE = 1002;
    private static final int TYPE_EMPTY = 1003;
    private static final int TYPE_ERROR = 1004;
    private static final int TYPE_ERROR_CONNECTION = 1005;
    private static final int TYPE_ERROR_LOADING = 1006;
    private static final int TYPE_ERROR_CONNECTION_LOADING = 1007;
    private int state = STATE_LOADING;

    private List<Specialist> specialistsList;
    private Context context;

    private boolean loading = false;
    private AdapterListener mListener;

    public AdapterWithStates(Context context,
                             List<Specialist> specialistsList,
                             AdapterListener adapterListener) {
        this.specialistsList = specialistsList;
        this.context = context;
        this.mListener = adapterListener;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        switch (viewType) {
            case TYPE_LOADING:
                return new ViewHolders.LoadingViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.loading_row, parent, false));
            case TYPE_LOADING_MORE:
                return new ViewHolders.LoadMoreProgressViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.load_more_row, parent, false));
            case TYPE_EMPTY:
                return new ViewHolders.EmptyViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.error_empty_row, parent, false));
            case TYPE_ERROR:
                if (specialistsList.size() > 0) {
                    return new ViewHolders.LoadMoreProgressViewHolder(LayoutInflater.from(context)
                            .inflate(R.layout.load_more_row, parent, false));
                } else {
                    return new ViewHolders.ErrorViewHolder(LayoutInflater.from(context)
                            .inflate(R.layout.error_row, parent, false));
                }
            case TYPE_ERROR_CONNECTION:
                if (specialistsList.size() > 0) {
                    return new ViewHolders.LoadMoreProgressViewHolder(LayoutInflater.from(context)
                            .inflate(R.layout.load_more_row, parent, false));
                } else {
                    return new ViewHolders.ErrorConnectionViewHolder(LayoutInflater.from(context)
                            .inflate(R.layout.error_connection_row, parent, false));
                }
            case TYPE_ERROR_LOADING:
                return new ViewHolders.ErrorLoadMoreViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.error_load_more_row, parent, false));
            case TYPE_ERROR_CONNECTION_LOADING:
                return new ViewHolders.ErrorLoadMoreViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.error_connection_load_more_row, parent, false));
            default:
                return new MyViewHolder(LayoutInflater.from(context)
                        .inflate(R.layout.specialist_short_layout_row, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ViewHolders.LoadingViewHolder) {
            onBindLoadingViewHolder((ViewHolders.LoadingViewHolder) holder);

        } else if (holder instanceof ViewHolders.LoadMoreProgressViewHolder) {
            onBindLoadMoreViewHolder((ViewHolders.LoadMoreProgressViewHolder) holder, position);

        } else if (holder instanceof ViewHolders.ErrorLoadMoreViewHolder) {
            onBindErrorLoadMoreViewHolder((ViewHolders.ErrorLoadMoreViewHolder) holder, position);

        } else if (holder instanceof ViewHolders.EmptyViewHolder) {
            onBindEmptyViewHolder((ViewHolders.EmptyViewHolder) holder, position);

        } else if (holder instanceof ViewHolders.ErrorViewHolder) {
            onBindErrorViewHolder((ViewHolders.ErrorViewHolder) holder, position);

        } else if (holder instanceof ViewHolders.ErrorConnectionViewHolder) {
            onBindErrorConnectionViewHolder((ViewHolders.ErrorConnectionViewHolder) holder, position);

        } else if (holder instanceof MyViewHolder) {
            onBindDefaultViewHolder((MyViewHolder) holder, position);

        }
    }

    private void onBindDefaultViewHolder(MyViewHolder holder, int position) {
        Specialist specialist = specialistsList.get(position);
        holder.mName.setText(specialist.getFullName());
        holder.mService.setText(specialist.getSex());
        holder.mRatingBar.setRating(specialist.getRating() != null ? Float.parseFloat(specialist.getRating()) : 0);
    }

    private void onBindErrorViewHolder(ViewHolders.ErrorViewHolder holder, final int position) {
        holder.retryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mListener != null)
                    mListener.onRetryClickListener(position);
            }
        });
    }

    private void onBindErrorConnectionViewHolder(ViewHolders.ErrorConnectionViewHolder holder, final int position) {
        holder.retryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mListener != null)
                    mListener.onRetryClickListener(position);
            }
        });
    }

    private void onBindEmptyViewHolder(ViewHolders.EmptyViewHolder holder, final int position) {
        holder.mEmptyLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mListener != null)
                    mListener.onEmptyClickListener(position);
            }
        });
    }

    private void onBindLoadMoreViewHolder(ViewHolders.LoadMoreProgressViewHolder holder, final int position) {
            holder.errorLayout.setVisibility(View.GONE);
            holder.progressBar.setVisibility(View.VISIBLE);
            holder.progressBar.setIndeterminate(true);
            if (!loading) {
                if (mListener != null) {
                    mListener.onLoadMore(position);
                }
                loading = true;
            }
    }

    private void onBindErrorLoadMoreViewHolder(ViewHolders.ErrorLoadMoreViewHolder holder, final int position) {
        holder.retryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mListener != null)
                    mListener.onRetryClickListener(position);
            }
        });
    }

    private void onBindLoadingViewHolder(ViewHolders.LoadingViewHolder holder) {
        holder.progressBar.setIndeterminate(true);
    }

    @Override
    public int getItemCount() {
        switch (state) {
            case STATE_LOADING:
            case STATE_EMPTY:
            case STATE_ERROR_CONNECTION:
            case STATE_ERROR:
                if (specialistsList != null && specialistsList.size() != 0)
                    return specialistsList.size();
                else
                    return 1;
            default:
                return specialistsList.size();
        }
    }

    @Override
    public int getItemViewType(int position) {
        switch (state) {
            case STATE_LOADING:
                if (specialistsList.size() == 0)
                    return TYPE_LOADING;
                else if (specialistsList.get(position) == null)
                    return TYPE_LOADING_MORE;
                else
                    return TYPE_NORMAL;
            case STATE_EMPTY:
                return TYPE_EMPTY;
            case STATE_ERROR:
                if (specialistsList.size() == 0)
                    return TYPE_ERROR;
                else if (specialistsList.get(position) == null)
                    return TYPE_ERROR_LOADING;
                else
                    return TYPE_NORMAL;
            case STATE_ERROR_CONNECTION:
                if (specialistsList.size() == 0)
                    return TYPE_ERROR_CONNECTION;
                else if (specialistsList.get(position) == null)
                    return TYPE_ERROR_CONNECTION_LOADING;
                else
                    return TYPE_NORMAL;
            default:
                if (specialistsList.get(position) != null) {
                    return TYPE_NORMAL;
                } else {
                    return TYPE_LOADING_MORE;
                }
        }
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        CardView mRoot;
        TextView mName;
        TextView mService;
        RatingBar mRatingBar;

        MyViewHolder(View view) {
            super(view);
            mRoot = view.findViewById(R.id.root_layout);
            mName = view.findViewById(R.id.name_tv);
            mService = view.findViewById(R.id.service_tv);
            mRatingBar = view.findViewById(R.id.ratingBar);

            mRoot.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (mListener != null)
                        mListener.onItemClickListener(getAdapterPosition());
                }
            });
        }
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyDataSetChanged();
    }

    public void update(List<Specialist> newList) {
        specialistsList = newList;
        notifyItemInserted(specialistsList.size());
    }

    public void removeLastItem() {
        if (specialistsList != null && specialistsList.size() != 0)
            specialistsList.remove(specialistsList.size() - 1);
        notifyDataSetChanged();
    }

    public void setLoaded() {
        state = STATE_NORMAL;
        loading = false;
    }
}

Можно ли уменьшить или унаследовать, оставив метод onBindDefaultViewHolder и класс MyViewHolder для реализации?

1 Ответ

0 голосов
/ 21 октября 2018

Вы можете сделать свой SpecialistAdapter абстрактным:

public abstract class SpecialistAdapter extends RecyclerView.Adapter {
    //...

    public abstract RecyclerView.ViewHolder makeViewHolder();
}

Затем, когда вы расширяете SpecialistAdapter, вам все равно потребуется реализовать onBindViewHolder(), а также новый метод makeViewHolder().

В onCreateViewHolder() вы можете вызвать makeViewHolder() вместо создания нового MyViewHolder экземпляра:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder vh;
    if (viewType == VIEW_ITEM) {
        vh = makeViewHolder();
    } else {
        View v = LayoutInflater.from(context).inflate(R.layout.loading_row, parent, false);
        vh = new ProgressViewHolder(v);
    }
    return vh;
}
...