如何在RecycleView

时间:2016-12-22 11:38:08

标签: android android-recyclerview picasso android-cardview cardview

我有一个带有CardViews回收视图的产品列表。每个CardView都有一个产品图片。

问题是我得到了

  

" java.lang.OutOfMemoryError"

。 我想是因为我在我的RecycleView适配器中使用Picasso。

以下是代码:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.List;

import uk.co.something.R;
import uk.co.something.Product;


public class ProductListAdapter extends RecyclerView.Adapter<ProductListAdapter.ViewHolder> {
    private List<Product> products;
    private int rowLayout;
    private Context appContext;

    public ProductListAdapter(List<Product> products, int rowLayout, Context appContext) {
        this.products = products;
        this.rowLayout = rowLayout;
        this.appContext = appContext;
    }

    @Override
    public ProductListAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);
        return new ProductListAdapter.ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ProductListAdapter.ViewHolder viewHolder, int i) {
        Product product = products.get(i);
        Picasso.with(appContext).load(product.getUrl().getImage()).into(viewHolder.image);
        Picasso.with(appContext).load(product.getRetailer().getIcon()).into(viewHolder.logo);
        String productPrice = (product.getPrice().getDiscounted() == null || Double.parseDouble(product.getPrice().getDiscounted()) <= 0) ? product.getPrice().getCost() : product.getPrice().getDiscounted();
        viewHolder.price.setText("\u00a3" + productPrice);

    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView image;
        public ImageView logo;
        public TextView price;

        ViewHolder(View itemView) {
            super(itemView);
            image = (ImageView) itemView.findViewById(R.id.product_list_cardview_image);
            logo = (ImageView) itemView.findViewById(R.id.product_list_cardview_logo);
            price = (TextView) itemView.findViewById(R.id.product_list_cardview_price);
        }

    }
}

我得到的错误就是这个:

  

E / AndroidRuntime:致命异常:主要                 处理:uk.co.lexel.dimble,PID:5503                 java.lang.OutOfMemoryError:无法分配带有4269112个空闲字节的11760012字节分配和4MB直到OOM                     at dalvik.system.VMRuntime.newNonMovableArray(Native Method)                     在android.graphics.BitmapFactory.nativeDecodeAsset(本机方法)                     在android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)                     在android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)                     在android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080)                     在android.content.res.Resources.loadDrawableForCookie(Resources.java:2635)                     在android.content.res.Resources.loadDrawable(Resources.java:2540)                     在android.content.res.Resources.getDrawable(Resources.java:806)                     在android.content.Context.getDrawable(Context.java:458)                     在android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:30)                     在android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:372)                     在android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202)                     在android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190)                     在android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)                     在android.support.v7.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:54)                     在android.support.v7.widget.AppCompatImageView。(AppCompatImageView.java:66)                     在android.support.v7.widget.AppCompatImageView。(AppCompatImageView.java:56)                     在android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106)                     在android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1021)                     在android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1080)                     在android.support.v4.view.LayoutInflaterCompatHC $ FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:47)                     在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:746)                     在android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)                     在android.view.LayoutInflater.rInflate(LayoutInflater.java:835)                     在android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)                     在android.view.LayoutInflater.rInflate(LayoutInflater.java:838)                     在android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)                     在android.view.LayoutInflater.rInflate(LayoutInflater.java:838)                     在android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)                     在android.view.LayoutInflater.inflate(LayoutInflater.java:515)                     在android.view.LayoutInflater.inflate(LayoutInflater.java:423)                     at uk.co.something.controllers.activities.ProductListAdapter.onCreateViewHolder(ProductListAdapter.java:35)                     at uk.co.something.controllers.activities.ProductListAdapter.onCreateViewHolder(ProductListAdapter.java:22)                     在android.support.v7.widget.RecyclerView $ Adapter.createViewHolder(RecyclerView.java:6290)                     在android.support.v7.widget.RecyclerView $ Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478)                     在android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:270)                     在android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:324)                     在android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:337)                     在android.support.v7.widget.GapWorker.prefetch(GapWorker.java:344)                     在android.support.v7.widget.GapWorker.run(GapWorker.java:370)                     在android.os.Handler.handleCallback(Handler.java:739)                     在android.os.Handler.dispatchMessage(Handler.java:95)                     在android.os.Looper.loop(Looper.java:148)                     在android.app.ActivityThread.main(ActivityThread.java:5417)                     at java.lang.reflect.Method.invoke(Native Method)                     在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:726)                     在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

在日志中说问题就在这里:

View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);

有人可以帮助我吗?

3 个答案:

答案 0 :(得分:1)

您的应用超出了提供给它的总内存,导致出现java.lang.OutOfMemoryError错误。

在您的应用中,这可能是因为您在recyclerView中显示的图片尺寸较大,并且在显示之前不会缩放到图像视图的尺寸

使用Picasso正确缩放图像,可以使用Picasso中的.fit()方法

例如

Picasso  
.with(context)
.load(UsageExampleListViewAdapter.eatFoodyImages[0])
.fit()
// call .centerInside() or .centerCrop() to avoid a stretched image
.into(imageViewFit);

或者代替毕加索,你可以使用Glide

  compile 'com.github.bumptech.glide:glide:3.7.0'

例如

Glide.with(context) 
     .load(image)
     .asBitmap()‌​.transform(new CenterCrop(context)) 
     .diskCacheStrategy( DiskCacheStrategy.NONE ) 
     .skipMemoryCache( true ) 
     .int‌​o(your_imageview)

您还可以通过在Manifest中启用大堆来增加分配给应用程序的默认内存

例如

android:largeHeap="true"

有关缩放图像和加载图像的更多信息,您可以查看此链接:https://developer.android.com/training/displaying-bitmaps/load-bitmap.html

答案 1 :(得分:0)

防止java.lang.OutOfMemoryError简单使用Glide Image Loader和平滑滚动。使用以下链接 Glide Tutorial

答案 2 :(得分:0)

在我的项目中,我几乎使用了所有库来加载recylerview中的图像,但是所有库都存在一些问题。但是,在使用recyclerview加载图像时,Universal Image Loader是最好的。