使用recycleview实现item多布局踩的坑
来源:互联网 发布:mac的safari无法退出 编辑:程序博客网 时间:2024/05/21 08:21
关于使用recycleview写多种布局布局遇到的坑
最近项目中遇到多种布局嵌套使用情况,为了不多麻烦去写自定义控件监听事件的分发,便使用了recycleview.对于第一次在项目中使用这个玩意,在看过官方文档后并不是很理解其介绍(主要是全英文),于是乎在CSDN怼了个中文注解的示例demo来用,于是乎就有了下面的这个问题.
1. 首先看原型图
2. 服务器返回的数据
3.我的代码(recycleview使用adapter部分出自CSDN示列demo).
Activity:
package com.example.administrator.a3dmark.detail_shop;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.administrator.a3dmark.Activity.BaseActivity;
import com.example.administrator.a3dmark.R;
import com.example.administrator.a3dmark.adapter.ShopAdapter;
import com.example.administrator.a3dmark.bean.Banners;
import com.example.administrator.a3dmark.bean.ShopGoods;
import com.example.administrator.a3dmark.util.Contants;
import com.example.administrator.a3dmark.util.ItemDivider;
import com.example.administrator.a3dmark.util.SharedUtil;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.callback.StringCallback;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import okhttp3.Call;
import okhttp3.Response;
/**
* 店铺
* Created by Administrator on 2017/3/8.
*/
public class Shop_ActivityextendsBaseActivity {
@BindView(R.id.image_title_white_back)
ImageView imageTitleWhiteBack;
@BindView(R.id.tv_title_white)
TextView tvTitleWhite;
@BindView(R.id.tv_title_white_vice)
TextView tvTitleWhiteVice;
Intent intent;
@BindView(R.id.tv_collection_title)
TextView tvCollectionTitle;
@BindView(R.id.tv_title_num)
TextView tvTitleNum;
@BindView(R.id.ll_title)
LinearLayout llTitle;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
private String bussiness_id;
private String userid;
//轮播图List<bean>对象
privateArrayList<Banners>Flybanners= newArrayList<>();
//商品List<bean>对象
privateArrayList<ShopGoods>goodses= newArrayList<ShopGoods>();
private ShopAdapter adapter;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shop_activity);
ButterKnife.bind(this);
intent = getIntent();
bussiness_id =intent.getStringExtra("bussiness_id");
Toast.makeText(Shop_Activity.this,bussiness_id, Toast.LENGTH_SHORT).show();
userid = (String) SharedUtil.getParam(this,"userid","");
llTitle.setVisibility(View.VISIBLE);
recyclerView.setLayoutManager(newGridLayoutManager(recyclerView.getContext(),3, GridLayoutManager.VERTICAL,false));
recyclerView.addItemDecoration(newItemDivider().setDividerWith(this,20));
adapter = new ShopAdapter(Shop_Activity.this);
initGradData();
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(newShopAdapter.OnRecyclerViewItemClickListener() {
@Override
public voidonItemClick(View view) {
int position =recyclerView.getChildAdapterPosition(view);
startActivity(new Intent(Shop_Activity.this,Boutique_Detail.class)
.putExtra("goods_id",goodses.get(position).getId())
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
);
}
});
imageTitleWhiteBack.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View view) {
finish();
}
});
}
//商品接口
private voidinitGradData() {
final ProgressDialog mDialog = ProgressDialog.show(this,"获取数据","获取数据中");
OkGo.post(Contants.DTORE)
.params("bussinessId",bussiness_id)
.execute(new StringCallback() {
@Override
public voidonSuccess(String s, Call call, Response response) {
Log.d("code===initGradData", s);
mDialog.dismiss();
try {
JSONObject json = newJSONObject(s);
if (s.indexOf("error") != -1) {//有错误
Toast.makeText(Shop_Activity.this, json.getString("error"), Toast.LENGTH_SHORT).show();
return;
}
JSONObject success = json.getJSONObject("success");
tvTitleWhite.setText(success.getString("shopName"));
tvTitleNum.setText("店铺号:"+success.getString("introduce"));
JSONArray info = success.getJSONArray("goodsInfoArray");
for (inti =0; i < info.length(); i++) {
JSONObject obj = info.getJSONObject(i);
ShopGoods shopgoods = newShopGoods();
shopgoods.setGoodsname(obj.getString("goodsName"));
shopgoods.setId(obj.getString("goodsId"));
shopgoods.setImages(obj.getString("img"));
shopgoods.setPricenow(obj.getString("priceNow"));
goodses.add(shopgoods);
}
adapter.setGoods(goodses);
JSONArray showPage = success.getJSONArray("showPage");
for (intj =0; j < showPage.length(); j++){
JSONObject page = info.getJSONObject(j);
Banners banners = newBanners();
//banners.setId(page.getString("id"));
banners.setImg(page.getString("img"));
Flybanners.add(banners);
}
adapter.setFlybanners(Flybanners);
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public voidonError(Call call, Response response, Exception e) {
super.onError(call, response, e);
mDialog.dismiss();
Toast.makeText(Shop_Activity.this, e.toString(), Toast.LENGTH_LONG).show();
}
});
}
}
Adapter:
package com.example.administrator.a3dmark.adapter;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.example.administrator.a3dmark.R;
import com.example.administrator.a3dmark.bean.Banners;
import com.example.administrator.a3dmark.bean.ShopGoods;
import com.recker.flybanner.FlyBanner;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2017/3/8.
*/
public class ShopAdapterextendsRecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
//轮播图List<bean>对象
privateArrayList<Banners>Flybanners;
//商品List<bean>对象
privateArrayList<ShopGoods>goods;
//type
public static final intTYPE_1= 0xff0111;
public static final int TYPE_MAIN=0xffffff;
public ShopAdapter(Context context) {
this.context= context;
Flybanners = new ArrayList<>();
goods = new ArrayList<>();
}
public ArrayList<Banners> getFlybanners() {
return Flybanners;
}
public void setFlybanners(ArrayList<Banners> flybanners) {
Flybanners = flybanners;
}
public List<ShopGoods> getGoods() {
return goods;
}
public void setGoods(ArrayList<ShopGoods> goods) {
this.goods= goods;
}
//自定义监听事件
public static interfaceOnRecyclerViewItemClickListener {
void onItemClick(View view);
//void onItemLongClick(View view);
}
//监听接口
privateShopAdapter.OnRecyclerViewItemClickListenermOnItemClickListener=null;
//监听实现
public voidsetOnItemClickListener(ShopAdapter.OnRecyclerViewItemClickListener listener) {
mOnItemClickListener = listener;
}
@Override
publicRecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
switch (viewType){
case TYPE_1:
return new ShopAdapter.MyViewHolder1(LayoutInflater.from(parent.getContext()).inflate(R.layout.md_recycle_item_type1, parent, false));
case TYPE_MAIN:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_shop_typemain, parent,false);
view.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View view) {
if (mOnItemClickListener!=null) {
mOnItemClickListener.onItemClick(view);
}
}
});
return new ShopAdapter.MyViewHolderMain(view);
default:
Log.d("error","viewholder is null");
return null;
}
}
@Override
public voidonBindViewHolder(RecyclerView.ViewHolder holder,intposition) {
if (holder instanceof ShopAdapter.MyViewHolder1){
bindType1((ShopAdapter.MyViewHolder1) holder, position);
}else if (holderinstanceofShopAdapter.MyViewHolderMain){
bindTypeMain((ShopAdapter.MyViewHolderMain) holder, position);
}
}
/**
* Main RecyclerView getItemCount
* @return
*/
@Override
public intgetItemCount() {
return getGoods().size();
}
@Override
public intgetItemViewType(intposition) {
if (position == 0){
return TYPE_1;
}else {
return TYPE_MAIN;
}
}
@Override
public voidonAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if(manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(newGridLayoutManager.SpanSizeLookup() {
@Override
public intgetSpanSize(intposition) {
int type = getItemViewType(position);
switch (type){
case TYPE_1:
return gridManager.getSpanCount();
default:
return 1;
}
}
});
}
}
private void bindType1(ShopAdapter.MyViewHolder1 holder,intposition){
//轮播图URL
ArrayList<String> ImagesUrl =newArrayList();
if (getFlybanners().size() !=0) {
for (Banners flyBanners : getFlybanners()) {
ImagesUrl.add(flyBanners.getImg());
}
holder.flyBanner.setImagesUrl(ImagesUrl);
}
holder.flyBanner.setOnItemClickListener(newFlyBanner.OnItemClickListener() {
@Override
public voidonItemClick(intposition) {
// Intent intent = new Intent(context, Boutique_Detail.class);
// intent.putExtra("goods_id", Flybanners.get(position).getId());
// context.startActivity(intent);
}
});
}
private void bindTypeMain(ShopAdapter.MyViewHolderMain holder,intposition){
Glide.with(context).load(getGoods().get(position).getImages()).fitCenter().placeholder(R.drawable.icon_empty).into(holder.img);
holder.textprice.setText(getGoods().get(position).getPricenow());
holder.name.setText(getGoods().get(position).getGoodsname());
holder.buy.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View view) {
//去试衣间
}
});
}
public class MyViewHolder1extendsRecyclerView.ViewHolder {
public FlyBannerflyBanner;
public MyViewHolder1(View itemView) {
super(itemView);
flyBanner = (FlyBanner) itemView.findViewById(R.id.banner);
}
}
public class MyViewHolderMainextendsRecyclerView.ViewHolder {
public ImageViewimg;//商品图片
publicTextViewname;//商品简介
publicTextViewtextprice;//商品价格
publicTextViewbuy;//立即购买
publicMyViewHolderMain(finalView itemView) {
super(itemView);
img = (ImageView) itemView.findViewById(R.id.img);
name = (TextView) itemView.findViewById(R.id.name);
textprice = (TextView) itemView.findViewById(R.id.price);
buy = (Button) itemView.findViewById(R.id.buy);
}
}
}
问题:
在运行项目后,服务器明明返回给了一个如下红色方框标记的商品数据,而却没有显示出来.
细挖代码后发现,是如下代码位置出了问题.
/**
* Main RecyclerView getItemCount
* @return
*/
@Override
public intgetItemCount() {
return getGoods().size();
}
@Override
public intgetItemViewType(intposition) {
if (position == 0){
return TYPE_1;
}else {
return TYPE_MAIN;
}
}
当getItemCount的值return的是getGoods().size();
而getItemViewType的position == 0时加载了另一个布局,
这”另一个布局”作为了getItemCount的一个item而正好
getGoods().size()为1,也就是position == 0.
就出现了本该有的一个商品却没有显示,使数据出现丢失的情况.
理所当然getItemCount应该返回returngetGoods().size()+1;
而当我重新运行项目竟然报错 java.lang.IndexOutOfBoundsException(数组下标越界异常)
根据报错位置找到是下划线位置报错:
private void bindTypeMain(ShopAdapter.MyViewHolderMain holder,intposition){
Glide.with(context).load(getGoods().get(position).getImages()).fitCenter().placeholder(R.drawable.icon_empty).into(holder.img);
holder.textprice.setText(getGoods().get(position).getPricenow());
holder.name.setText(getGoods().get(position).getGoodsname());
holder.buy.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View view) {
//去试衣间
}
});
}
当getGoods().size()+1后,position的值就不能再匹配对应的数据,
position是大于getGoods().size()的.
反复调试后:
private void bindTypeMain(ShopAdapter.MyViewHolderMain holder, int position){
ShopGoods shopGoods = null;
if (position <= getGoods().size()) {
shopGoods = getGoods().get(position-1);
}
Glide.with(context).load(shopGoods.getImages()).fitCenter().placeholder(R.drawable.icon_empty).into(holder.img);
holder.textprice.setText(shopGoods.getPricenow());
holder.name.setText(shopGoods.getGoodsname());
holder.buy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//去试衣间
}
});
}
这样设置后运行项目,看到界面(喜极而泣)终于显示出来了
好接着开始写点击事件,写好后点击一看toast,靠商品对应的ID不对?
ID出现乱序.靠什么鬼?
再挖代码,挖挖找找....真TMD(别乱猜中文,我反正是想说”他妹的”)不负有心人,再activity点击事件的回调中这样写:
//item的点击事件
adapter.setOnItemClickListener(new ShopAdapter.OnRecyclerViewItemClickListener() {
@Override
public void onItemClick(View view) {
ShopGoods shopGoods = null;
int position = recyclerView.getChildAdapterPosition(view);
if (position <= goodses.size()) {
shopGoods = goodses.get(position-1);
}
startActivity(new Intent(Shop_Activity.this,Boutique_Detail.class)
.putExtra("goods_id",shopGoods.getId())
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
);
}
});
再次以怀疑人生的心情运行一次项目,打开界面,点击,
wo~~kao~kao~kao~~~
终于搞定!!!
(转眼第二天测试!!!)然而程序总是喜欢跟哥开玩笑,当我再次运行项目(日志显示)服务器给我返回了两个商品数据,而测试手机界面确实也有两个商品数量,这里强调:是”数量”.很是奇怪第二个商品没任何数据?靠靠靠,又开始挖代码~挖啊挖,半小时过去了.然而并没有什么卵用!已接近崩溃了,早一万句草泥马已经飞奔过去.到了接近快一个小时的时候,发现了红色标注的地方:
private void bindTypeMain(ShopAdapter.MyViewHolderMain holder, int position){
ShopGoods shopGoods = null;
if (position <= getGoods().size()) {
shopGoods = getGoods().get(position-1);
}
Glide.with(context).load(shopGoods.getImages()).fitCenter().placeholder(R.drawable.icon_empty).into(holder.img);
holder.textprice.setText(shopGoods.getPricenow());
holder.name.setText(shopGoods.getGoodsname());
holder.buy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//去试衣间
}
});
}
就这个判断,正确判断应该是
if (position <= getGoods().size()+1) {
shopGoods = getGoods().get(position-1);
}
在黑字标注的地方 +1 欧了运行项目显示正常!点击商品异常退出应用!
又TM 什么鬼?
再去点击事件查看 靠靠啊靠~~
adapter.setOnItemClickListener(new ShopAdapter.OnRecyclerViewItemClickListener() {
@Override
public void onItemClick(View view) {
ShopGoods shopGoods = null;
int position = recyclerView.getChildAdapterPosition(view);
if (position <= goodses.size()+1) {
shopGoods = goodses.get(position-1);
}
startActivity(new Intent(Shop_Activity.this,Boutique_Detail.class)
.putExtra("goods_id",shopGoods.getId())
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
);
}
});
原来少 +1 ,加上运行项目,显示正常,点击商品跳转正常!
这次才算真正的终于搞定!!!
- 使用recycleview实现item多布局踩的坑
- recycleview多item布局的实现(简单聊天界面)
- RecycleView多Item布局
- RecycleView实现混合Item布局
- 关于recycleview的item的布局问题
- RecycleView实现多布局
- 关于Recycleview返回多个item布局
- RecycleView的多布局
- recycleView的多布局
- Android开发笔记之RecycleView加载不同item布局的实现
- RecycleView实现复杂的布局
- RecycleView如何实现item的点击事件
- RecycleView+BaseRecycleViewAdapterHelper多布局实现
- 对RecycleView的多种item布局的封装
- RecycleView 的多条目布局
- Android RecycleView 的多布局
- RecycleView item点击事件实现,item放大缩小动画布局不变形
- 2.6 ListView Item多布局的实现
- Java并发与多线程图文教程
- Java开发中文乱码的几种解决方法
- angular.element方法汇总
- (译)XposedHelpers
- Spring(3): Bean
- 使用recycleview实现item多布局踩的坑
- 设计模式、框架、架构、平台的区别
- html5<canvas转换之万花筒>
- ecshop指定分类文章和产品调用
- 学习kotlin第六天_包、控制流、返回和跳转
- FFT后的物理意义
- 算法思路交流
- 第一篇 微信商城 开发前的准备工作
- Android性能优化--优化启动速度