滚动到特定位置时 Recyclerview 崩溃
Posted
技术标签:
【中文标题】滚动到特定位置时 Recyclerview 崩溃【英文标题】:Recyclerview crashed when scrolled to particular position 【发布时间】:2017-12-17 15:36:08 【问题描述】:
我有RecyclerView
,它有分页,当我滚动几次时它会崩溃。当我慢慢滚动时,它不会崩溃。我提供了适配器和活动代码。请让我知道我在这里犯的任何错误。我已经搜索过相同的问题,但我无法在此处发现错误。
private class GetTrending extends AsyncTask<Void, Void, Void>
BufferedReader bufferedReader = null;
private StringBuffer stringBuffer = new StringBuffer();
private JSONArray jArray = new JSONArray();
private int pageNum;
private boolean value;
public GetTrending(int pageNum, boolean value)
this.pageNum = pageNum;
this.value = value;
@Override
protected Void doInBackground(Void... params)
try
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet();
URI uri = new URI(getString(R.string.url) +
"products?bestsellers=on&items_per_page=24&page=" + pageNum + mWholeSaleUrlTag);
httpGet.setURI(uri);
httpGet.addHeader(BasicScheme.authenticate(
new UsernamePasswordCredentials(getString(R.string.username), getString(R.string.password)),
HTTP.UTF_8, false));
HttpResponse httpResponse;
Log.e("Trending-Before", "Date" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new Date()));
httpResponse = httpClient.execute(httpGet);
Log.e("Trending-After", "New Date" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new Date()));
InputStream inputStream = httpResponse.getEntity().getContent();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//Log.e("Hi", String.valueOf(bufferedReader));
String readLine = bufferedReader.readLine();
while (readLine != null)
stringBuffer.append(readLine);
//stringBuffer.append("\n");
readLine = bufferedReader.readLine();
//Log.e("BestSellers", String.valueOf(stringBuffer));
catch (IOException e)
e.printStackTrace();
catch (URISyntaxException e)
e.printStackTrace();
try
JSONObject prodObjects = new JSONObject(String.valueOf(stringBuffer));
jArray = prodObjects.optJSONArray("products");
if (jArray.length() < 24)
shouldFetchTrending = false;
for (int i = 0; i < jArray.length(); i++)
Home home = new Home();
prodObjects = jArray.getJSONObject(i);
home.setProduct_id(prodObjects.getString("product_id"));
// Log.e("Trending id", jobj.getString("product_id"));
home.setProduct_name(prodObjects.getString("product"));
NumberFormat nf = NumberFormat.getInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
home.setProduct_price(nf.format(Double.parseDouble(prodObjects.getString("price"))));
home.setProduct_listprice(nf.format(Double.parseDouble(prodObjects.getString("list_price"))));
String mAmount = prodObjects.getString("amount");
home.setAmount(mAmount);
Item item = new Item();
item.setName(prodObjects.getString("product"));
item.setProductId(prodObjects.getString("product_id"));
item.setPrice(nf.format(Double.parseDouble(prodObjects.getString("price"))));
item.setListPrice(nf.format(Double.parseDouble(prodObjects.getString("list_price"))));
item.setImage(prodObjects.getJSONObject("main_pair").getJSONObject("detailed").getString("image_path"));
item.setAmount(mAmount);
home.setProduct_image(prodObjects.getJSONObject("main_pair").getJSONObject("detailed").getString("image_path"));
if (prodObjects.getString("status").equalsIgnoreCase("A") && !prodObjects.getString("amount").equalsIgnoreCase("0"))
Sports.add(home);
trendingItemList.add(item);
// Log.e("Length", String.valueOf(Sports.size()));
catch (JSONException e)
e.printStackTrace();
return null;
protected void onPostExecute(Void result)
super.onPostExecute(result);
shouldFetchTrending = true;
if (value)
trendingItemAdapter = new ItemAdapter(HomeActivity.this, trendingItemList);
mTrendingRecyclerView.setAdapter(trendingItemAdapter);
trendingItemAdapter.notifyDataSetChanged();
mTrendingRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(HomeActivity.this, new RecyclerItemClickListener.OnItemClickListener()
@Override
public void onItemClick(View view, int position)
((CardView) view).setCardElevation(100);
Intent myintent = new Intent(HomeActivity.this, ProductPageActivity.class);
myintent.putExtra("Prodid", trendingItemList.get(position).getProductId());
myintent.putExtra("FromHome", "Home");
startActivity(myintent);
));
try
for (int i = 0; i < Sports.size(); ++i)
trendinglinear[i].setVisibility(View.VISIBLE);
tname[i].setText(Sports.get(i).getProduct_name());
tprice[i].setText(Sports.get(i).getProduct_price());
((View) tname[i].getParent()).setTag(Sports.get(i).getProduct_id());
String[] simg = new String[25];
simg[i] = Sports.get(i).getProduct_image();
//Log.e("image", simg[i]);
Picasso.with(getApplicationContext()).load(simg[i]).error(R.drawable.ic_launcher).resize(400, 400).into(timage[i]);
catch (Exception e)
//Toast.makeText(HomeActivity.this, "Failed to connect to internet Try again !", Toast.LENGTH_SHORT).show();
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder>
private List<Item> itemList;
private Context context;
private int lastPosition = -1;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.home_recycler_item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
@Override
public void onBindViewHolder(ViewHolder holder, int position)
Item item = itemList.get(position);
holder.tvName.setText(item.getName());
if(Integer.valueOf(item.getAmount()) == 0)
holder.tvOutofstack.setVisibility(View.VISIBLE);
else holder.tvOutofstack.setVisibility(View.INVISIBLE);
holder.tvPrice.setText(item.getPrice());
Picasso.with(context).load(item.getImage()).into(holder.ivImage);
setAnimation(holder.cardView, position);
@Override
public int getItemCount()
return itemList.size();
public static class ViewHolder extends RecyclerView.ViewHolder
public TextView tvName,tvOutofstack;
public TextView tvPrice;
public ImageView ivImage;
public CardView cardView;
public ViewHolder(View itemView)
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
tvOutofstack = (TextView) itemView.findViewById(R.id.item_adapter_tv);
tvPrice = (TextView) itemView.findViewById(R.id.tv_price);
ivImage = (ImageView) itemView.findViewById(R.id.iv_image);
cardView = (CardView) itemView.findViewById(R.id.card_view);
public ItemAdapter(Context context, List<Item> itemList)
this.itemList = itemList;
this.context = context;
private void setAnimation(View viewToAnimate, int position)
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
显示一些错误(日志):
java.lang.InternalError: 线程在运行时关闭期间启动 07-13 09:01:29.721 32089-1640/? W / System.err:在 java.lang.Thread.nativeCreate(本机方法) - - - - - 和 - - - - - GC_FOR_ALLOC 释放 1057K,释放 20% 115415K/143088K,暂停 295ms,共 295ms 07-13 11:57:15.692 11792-12003/com.dealmaar.customer I/dalvikvm-heap:将堆(碎片情况)增加到 116.585MB,分配 4000012 字节 07-13 11:57:15.936 11792-12001/com.dealmaar.customer D/dalvikvm: GC_FOR_ALLOC freed
【问题讨论】:
请发布您的错误日志 发布你的堆栈跟踪。为什么要使用异步任务和 http 客户端,因为您可以使用 Retrofit 轻松调用网络并使用 jackson 解析器解析 json,这将消除大量代码 没有错误日志。 【参考方案1】:应用程序因内存管理失败而崩溃,这里每个项目都分配了动画,并且应用的动画没有清除。我花了 1 天时间解决了你的问题,它对我有用。
@Override public void onViewDetachedFromWindow(ViewHolder holder)
super.onViewDetachedFromWindow(holder);
((ViewHolder)holder).clearAnimation();
在我的 ViewHolder 中添加方法:
public void clearAnimation()
itemView.clearAnimation();
【讨论】:
【参考方案2】:您有内存不足异常。 在某些设备中,当您通过最大堆时,它不会显示任何日志,并且 JVM 只会终止您的应用程序。 当你缓慢滚动时,你让 JVM 完成它的垃圾收集过程,但是当你快速滚动时,它没有足够的时间来完成它的任务,你会通过最大堆。 我看到您持有对视图列表和 ImageViews 的引用。
try
for (int i = 0; i < Sports.size(); ++i)
trendinglinear[i].setVisibility(View.VISIBLE);
tname[i].setText(Sports.get(i).getProduct_name());
tprice[i].setText(Sports.get(i).getProduct_price());
((View) tname[i].getParent()).setTag(Sports.get(i).getProduct_id());
String[] simg = new String[25];
simg[i] = Sports.get(i).getProduct_image();
//Log.e("image", simg[i]);
Picasso.with(getApplicationContext()).load(simg[i]).error(R.drawable.ic_launcher).resize(400, 400).into(timage[i]);
catch (Exception e)
//Toast.makeText(HomeActivity.this, "Failed to connect to internet Try again !", Toast.LENGTH_SHORT).show();
这可能是堆达到最大大小的原因之一。
【讨论】:
【参考方案3】:你在主线程中做了太多的工作。系统已经超过了它的限制,要执行你的进程需要大量的资源,它会冻结主 UI 线程导致 ANR 错误。我建议您使用AsyncTask
在后台线程中执行所有 API 调用和 JSON 解析。
【讨论】:
以上是关于滚动到特定位置时 Recyclerview 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
RecyclerView - 如何平滑滚动到嵌套滚动视图内某个位置的项目顶部?
应用程序在 recyclerview 滚动 android kotlin 时崩溃
使用 Recycler View 将房间数据库滚动到特定位置