ListView到RecyclerView Migration for CustomView

use*_*470 2 android listview android-listview android-recyclerview

我认为我的项目需要从ListView转移到RecyclerView.我正面临一些设计问题.

在我当前的ListView实现中,我使用CustomView而不是在那里进行膨胀.这是我当前的getView()

public View getView(int position, View containerRow, ViewGroup parent) {
        CustomView customView;
        if (containerRow == null) customView = new CustomView(mContext);
        else customView = (CustomView) containerRow;

        DataModel dataModel = getModelForPosition(position);
        if (dataModel != null) {
            customView.showView(singleDcyde,position);
        }
        return customView;

}
Run Code Online (Sandbox Code Playgroud)

这里showView管理填充textViews,图像自定义LayoutParams和许多其他东西(2000行).

现在,当我计划搬到RecylerView时,我对我的设计感到困惑. - 我是否需要在RecyclerView.ViewHolder类中重写整个内容然后在onBindViewHolder中绑定它们?

因为我已经为Listview编写了大量代码,我不想重写/移动整个东西从CustomView返回到ViewHolder.

什么是使设计与RecyclerView理念保持同步的最佳方法.

ata*_*ulm 6

将ListView适配器转换为RecyclerView.Adapter非常简单 - 我为以下两种实现编写了骨架:

private static class MyRecyclerViewAdapter extends RecyclerView.Adapter<CustomViewHolder> {

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        CustomView view = createNewCustomView();
        return new CustomViewHolder(view);
    }

    private CustomView createNewCustomView() {
        // whatever you need to do to create - I would suggest create from XML rather new'ing up directly
        return null;
    }

    @Override
    public void onBindViewHolder(CustomViewHolder holder, int position) {
        // bind the data
        DataModel dataModel = getModelForPosition(position);
        holder.getCustomView().showView(dataModel, position);
    }

    private DataModel getModelForPosition(int position) {
        // TODO: however you did getModelForPosition(int)
        return null;
    }

    @Override
    public int getItemCount() {
        // TODO: same as getCount()
        return 0;
    }

}

private static class CustomViewHolder extends RecyclerView.ViewHolder {

    public CustomViewHolder(CustomView itemView) {
        super(itemView);
    }

    CustomView getCustomView() {
        return ((CustomView) itemView);
    }

}

private static class MyListViewAdapter extends BaseAdapter {

    @Override
    public int getCount() {
        // TODO: return correct list size
        return 0;
    }

    @Override
    public DataModel getItem(int position) {
        // TODO: however you did getModelForPosition(int)
        return null;
    }

    @Override
    public long getItemId(int position) {
        // however you do
        return 0;
    }

    @Override
    public View getView(int position, View containerRow, ViewGroup parent) {
        CustomView customView = ((CustomView) containerRow);
        if (customView == null) {
            customView = createNewCustomView();
        }

        // could just use getItem(int) here
        DataModel dataModel = getModelForPosition(position);

        // would it ever be null? if so, you'll have a blank list item
        if (dataModel != null) {
            customView.showView(dataModel.getSingleDcyde(), position);
        }
        return customView;
    }

    private CustomView createNewCustomView() {
        // whatever you need to do to create - I would suggest create from XML rather new'ing up directly
        return null;
    }

    private DataModel getModelForPosition(int position) {
        return getItem(position);
    }

}

private static class DataModel {

    Object getSingleDcyde() {
        // whatever this is
        return null;
    }

}

private static class CustomView extends View {

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void showView(Object singleDcyde, int position) {
        // bind
    }

}
Run Code Online (Sandbox Code Playgroud)

什么是使设计与RecyclerView理念保持同步的最佳方法.

RecyclerView背后的理念是关注点的分离; RecyclerView仅负责管理视图回收,LayoutManager将决定如何测量和定位视图,ViewHolder试图强制ViewHolder模式(一种避免多次不必要调用的方法findViewById()),而RecyclerView.Adapter是胶水它会挂起您的数据.

您现在被迫使用ViewHolder类.这个想法是findViewById()每个充气布局只进行一次所有调用(无论这个调用是否足够慢,可以进行辩论),例如:

private static final class CustomViewHolder extends RecyclerView.ViewHolder {

    private final TextView titleTextView;
    private final ImageView avatarImageView;

    public CustomViewHolder newInstance(CustomView itemView) {
        return new CustomViewHolder(
                itemView,
                ((TextView) itemView.findViewById(R.id.title_text_view)),
                ((ImageView) itemView.findViewById(R.id.avatar_image_view))
        );
    }

    private CustomViewHolder(CustomView itemView, TextView titleTextView, ImageView avatarImageView) {
        super(itemView);
        this.titleTextView = titleTextView;
        this.avatarImageView = avatarImageView;
    }

    public void setTitle(String title) {
        titleTextView.setText(title);
    }

    public void setAvatar(Drawable avatar) {
        avatarImageView.setImageDrawable(avatar);
    }

}
Run Code Online (Sandbox Code Playgroud)

实际上,由于您使用的是自定义视图,因此很可能(我希望)您已经findViewById(int)通过使用HolderView模式避免了多次调用.在这种情况下,您可以通过将其视为必要的邪恶来反抗强制使用ViewHolder的暴政:

private static final class CustomViewHolder extends RecyclerView.ViewHolder {

    public CustomViewHolder(CustomView itemView) {
        super(itemView);
    }

}

...
...

@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
    Foo foo = getFoo(position);
    ((CustomView) holder.itemView).myCustomBindMethod(foo);
}
Run Code Online (Sandbox Code Playgroud)