使用RecyclerView

时间:2017-04-08 05:01:32

标签: android android-recyclerview android-adapter android-json

根据this tutorial,我可以在一个屏幕上在RecyclerView上发布json内容(结果数组)

现在,我将json文件更改为:

 "page": 1, 
    "results": [ { ... } ],
    "menus": [ { ... } ]
}, "total_results": 5450, "total_pages": 273 }

现在我希望在同一屏幕上将RecycledView导入菜单数组。(在第一行)。 然后导入结果数组

菜单数组没有分页。

我为菜单创建了模型类( LastMedicMenu.java )。

我是菜鸟。所以现在,我想我必须改变适配器。

原始适配器是:

原始适配器:

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

    private static final int ITEM = 0;
    private static final int LOADING = 1;
    private static final String BASE_URL_IMG = "http://www.example.com/api/service/img";

    private List<LastMedicResult> medicResults;
    private Context context;

    private boolean isLoadingAdded = false;

    public MedicPaginationAdapter(Context context) {
        this.context = context;
        medicResults = new ArrayList<>();
    }

    public List<LastMedicResult> getMedics() {
        return medicResults;
    }


    public void setMedics(List<LastMedicResult> medicResults) {
        this.medicResults = medicResults;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case ITEM:
                viewHolder = getViewHolder(parent, inflater);
                break;
            case LOADING:
                View v2 = inflater.inflate(R.layout.item_progress, parent, false);
                viewHolder = new LoadingVH(v2);
                break;
        }
        return viewHolder;
    }

    @NonNull
    private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
        RecyclerView.ViewHolder viewHolder;
        View v1 = inflater.inflate(R.layout.service_list, parent, false);
        viewHolder = new MedicVH(v1);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        LastMedicResult result = medicResults.get(position); // Movie

        switch (getItemViewType(position)) {
            case ITEM:
                final MedicVH MedicVH = (MedicVH) holder;

                MedicVH.mMovieTitle.setText(result.getTitle());



                MedicVH.sLocation.setText(result.getServiceLocation());
                MedicVH.sType.setText(result.getServiceType());
                MedicVH.mMovieDesc.setText(result.getOverview());


                Glide
                        .with(context)
                        .load(BASE_URL_IMG + result.getPosterPath())
                        .listener(new RequestListener<String, GlideDrawable>() {
                            @Override
                            public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                                // TODO: 08/11/16 handle failure
                                MedicVH.mProgress.setVisibility(View.GONE);
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                                // image ready, hide progress now
                                MedicVH.mProgress.setVisibility(View.GONE);
                                return false;   // return false if you want Glide to handle everything else.
                            }
                        })
                        .diskCacheStrategy(DiskCacheStrategy.ALL)   // cache both original & resized image
                        .centerCrop()
                        .crossFade()
                        .into(MedicVH.mPosterImg);



                break;

            case LOADING:
//                Do nothing
                break;
        }

    }

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

    @Override
    public int getItemViewType(int position) {
        return (position == medicResults.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
    }


    /*
   Helpers
    */

    public void add(LastMedicResult r) {
        medicResults.add(r);
        notifyItemInserted(medicResults.size() - 1);
    }

    public void addAll(List<LastMedicResult> moveResults) {
        for (LastMedicResult result : moveResults) {
            add(result);
        }
    }

    public void remove(LastMedicResult r) {
        int position = medicResults.indexOf(r);
        if (position > -1) {
            medicResults.remove(position);
            notifyItemRemoved(position);
        }
    }

    public void clear() {
        isLoadingAdded = false;
        while (getItemCount() > 0) {
            remove(getItem(0));
        }
    }

    public boolean isEmpty() {
        return getItemCount() == 0;
    }


    public void addLoadingFooter() {
        isLoadingAdded = true;
        add(new LastMedicResult());
    }

    public void removeLoadingFooter() {
        isLoadingAdded = false;

        int position = medicResults.size() - 1;
        LastMedicResult result = getItem(position);

        if (result != null) {
            medicResults.remove(position);
            notifyItemRemoved(position);
        }
    }

    public LastMedicResult getItem(int position) {
        return medicResults.get(position);
    }


    protected class MedicVH extends RecyclerView.ViewHolder {
        private TextView mMovieTitle;
        private TextView mMovieDesc;
        private TextView sLocation;
        private TextView sType;
        private ImageView mPosterImg;
        private ProgressBar mProgress;

        public MedicVH(View itemView) {
            super(itemView);

            mMovieTitle = (TextView) itemView.findViewById(R.id.movie_title);


            mMovieDesc = (TextView) itemView.findViewById(R.id.movie_desc);



            sLocation = (TextView) itemView.findViewById(R.id.service_location);


            sType = (TextView) itemView.findViewById(R.id.service_type);


            mPosterImg = (ImageView) itemView.findViewById(R.id.movie_poster);
            mProgress = (ProgressBar) itemView.findViewById(R.id.movie_progress);

        }
    }


    protected class LoadingVH extends RecyclerView.ViewHolder {

        public LoadingVH(View itemView) {
            super(itemView);
        }
    }


}

请检查我要更改的步骤:

1- 原始代码:

private static final int ITEM = 0; // for search
private static final int LOADING = 1;// for progress bar

更改了代码:

private static final int ITEM = 0; // for search
private static final int MENU = 1; // for search1
private static final int LOADING = 2;// for progress bar

2 -

public MedicPaginationAdapter(Context context) {
        this.context = context;
        medicResults = new ArrayList<>();
    }

public MedicPaginationAdapter(Context context) {
    this.context = context;
    medicResults = new ArrayList<>();
    medicMenus = new ArrayList<>();
}

第3步:

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case ITEM:
                viewHolder = getViewHolder(parent, inflater);
                break;
            case LOADING:
                View v2 = inflater.inflate(R.layout.item_progress, parent, false);
                viewHolder = new LoadingVH(v2);
                break;
        }
        return viewHolder;
    }

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder viewHolder = null;
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());

        switch (viewType) {
            case ITEM:
                viewHolder = getViewHolder(parent, inflater,viewType);
                break;
            case MENU:
            viewHolder = getViewHolder(parent, inflater,viewType);
                break;
            case LOADING:
                View v2 = inflater.inflate(R.layout.item_progress, parent, false);
                viewHolder = new LoadingVH(v2);
                break;
        }
        return viewHolder;
    }

第4步:

private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
        RecyclerView.ViewHolder viewHolder;
        View v1 = inflater.inflate(R.layout.service_list, parent, false);
        viewHolder = new MedicVH(v1);
        return viewHolder;
    }

private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater, int viewType) {
        RecyclerView.ViewHolder viewHolder;
        View v1;
        if(ITEM == viewType)
        {
            v1 = inflater.inflate(R.layout.service_list, parent, false);
            viewHolder = new MedicVH(v1);
        }
        else
        {
            v1 = inflater.inflate(R.layout.service_munu_list, parent, false);
            viewHolder = new MedicMenuVH(v1);
        }
        return viewHolder;
    }

第5步:

public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        LastMedicResult result = medicResults.get(position); 


        switch (getItemViewType(position)) {
            case ITEM:
                final MedicVH MedicVH = (MedicVH) holder;

                MedicVH.mMovieTitle.setText(result.getTitle());
                ...


                break;

            case LOADING:
                   //Do nothing
                break;
        }

    }

public void onBindViewHolder(RecyclerView.ViewHolder holder,int position){

    LastMedicResult result = medicResults.get(position); 
    LastMedicResult menu = medicMenus.get(position); 
    switch (getItemViewType(position)) {
        case ITEM:
            final MedicVH MedicVH = (MedicVH) holder;

            MedicVH.mMovieTitle.setText(result.getTitle());
            ...


            break;
        case MENU:
            final MedicMenuVH MedicMenuVH = (MedicMenuVH) holder;

            MedicMenuVH .mMenuTitle.setText(menu.getTitle());
            ...


            break;


        case LOADING:
               //Do nothing
            break;
    }

}

步骤6:

@Override
    public int getItemViewType(int position) {
        return (position == medicResults.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
    }

public int getItemViewType(int position) {
        //return (position == medicResults.size() - 1 && isLoadingAdded) ? ITEM : ITEM;
        if(medicResults.get(position) instanceof LastMedicResult)
        {
            return (position == medicResults.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
        }
        else if(medicMenus.get(position) instanceof LastMedicMenu)
        {
            return (position == medicMenus.size() - 1 && isLoadingAdded) ? LOADING : MENU;
        }
        else
        {
            return LOADING;
        }
    }

第7步: AND最后添加这个类:

protected class MedicMenuVH extends RecyclerView.ViewHolder {
        private TextView mMenuTitle;


        public MedicMenuVH(View itemView) {
            super(itemView);

            mMenuTitle = (TextView) itemView.findViewById(R.id.menu_title);

        }
    }

完成所有更改后,它只能在RecyclerView中显示结果数组

我的错误代码是什么?请告诉我我该怎么办?

修改

根据答案,我将步骤5更改为:

@Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        LastMedicResult result = medicResults.get(position); // result
        LastMedicMenu menu = medicMenus.get(position);

        switch (getItemViewType(position)) {
            case ITEM:
                final MedicVH MedicVH = (MedicVH) holder;

                MedicVH.mMovieTitle.setText(result.getTitle());

                break;
            case MENU:
            {
                final MedicMenuVH MedicMenuVH = (MedicMenuVH) holder;

                MedicMenuVH.mMenuTitle.setText(menu.getTitle());
                break;
            }
            case LOADING:
                //  Do nothing
                break;
        }

    }

但是我在这行的错误日志中收到错误(应用程序将崩溃):

LastMedicMenu menu = medicMenus.get(position);

之前我为菜单创建了模型类。

为什么我会收到错误?

  

04-08 14:34:55.954 15584-15584 / com.example.teb E / AndroidRuntime:FATAL   例外:主要                                                                   java.lang.IndexOutOfBoundsException:索引0无效,大小为0                                                                       at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)                                                                       at java.util.ArrayList.get(ArrayList.java:304)                                                                       在com.example.teb.MedicPaginationAdapter.onBindViewHolder(MedicPaginationAdapter.java:105)

2 个答案:

答案 0 :(得分:0)

如果您已有菜单的模型类,则在 onBindViewHolder()中,只需将视图设置为在结果之前将菜单绑定到您拥有的布局

 LastMedicResult result = medicResults.get(position); 
 LastMedicMenus menus = medicMenus.get(position); //Custom Name 

    switch (getItemViewType(position)) {
        case ITEM:
            final MedicVH MedicVH = (MedicVH) holder;

            MedicVH.mMovieTitle.setText(result.getTitle());
            MedicVH.mMovieName.setText(menus.getFoo()); //This way
            ...

            break;
       ...
    }
}

答案 1 :(得分:0)

您已在 onBindViewHolder 中使用 medicResults 而非 medicMenus

  

LastMedicResult结果= medicResults.get(position);

问题是public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (getItemViewType(position)) { case ITEM: LastMedicResult result = medicResults.get(position); final MedicVH MedicVH = (MedicVH) holder; MedicVH.mMovieTitle.setText(result.getTitle()); ... break; case MENU: LastMedicMenus menus = medicMenus.get(position); final MedicMenuVH MedicMenuVH = (MedicMenuVH) holder; MedicMenuVH .mMenuTitle.setText(menus.getTitle()); ... break; case LOADING: //Do nothing break; } }

truecaller

您的 onBindViewHolder 应该像

custom view