【发布时间】:2017-04-08 05:01:32
【问题描述】:
根据this tutorial,我可以一屏在RecyclerView上发布json内容(结果数组)。
现在,我将 json 文件更改为:
"page": 1,
"results": [ { ... } ],
"menus": [ { ... } ]
}, "total_results": 5450, "total_pages": 273 }
现在我想将 menus array 导入到同一屏幕上的 RecyclerView。(在第一行)。 然后导入结果数组。
菜单数组没有分页。
我为菜单创建了模型类 (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;
}
第四步:
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;
}
}
第六步:
@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 步: 并且最后添加这个类:
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: 致命 例外:主要 java.lang.IndexOutOfBoundsException:索引 0 无效,大小为 0 在 java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) 在 java.util.ArrayList.get(ArrayList.java:304) 在 com.example.teb.MedicPaginationAdapter.onBindViewHolder(MedicPaginationAdapter.java:105)
【问题讨论】:
标签: android android-recyclerview android-adapter android-json