I have a product list made with a Recycle View with CardViews inside. Each CardView have an Image of the product.
The problem is that I'm getting a
"java.lang.OutOfMemoryError"
. I think is because I'm using Picasso in my RecycleView Adapter.
Here is the code:
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);
}
}
}
The error I'm getting is this one:
E/AndroidRuntime: FATAL EXCEPTION: main Process: uk.co.lexel.dimble, PID: 5503 java.lang.OutOfMemoryError: Failed to allocate a 11760012 byte allocation with 4269112 free bytes and 4MB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method) at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1080) at android.content.res.Resources.loadDrawableForCookie(Resources.java:2635) at android.content.res.Resources.loadDrawable(Resources.java:2540) at android.content.res.Resources.getDrawable(Resources.java:806) at android.content.Context.getDrawable(Context.java:458) at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:30) at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:372) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202) at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190) at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100) at android.support.v7.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:54) at android.support.v7.widget.AppCompatImageView.(AppCompatImageView.java:66) at android.support.v7.widget.AppCompatImageView.(AppCompatImageView.java:56) at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106) at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1021) at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1080) at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:47) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:746) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) at android.view.LayoutInflater.inflate(LayoutInflater.java:515) at 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) at android.support.v7.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:6290) at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5478) at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:270) at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:324) at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:337) at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:344) at android.support.v7.widget.GapWorker.run(GapWorker.java:370) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
In the logs says that the problem is here:
View v = LayoutInflater.from(viewGroup.getContext()).inflate(rowLayout, viewGroup, false);
Can someone help me?
You're getting
java.lang.OutOfMemoryError
error because your app is exceeding the total memory provided to it.In your app, this might be because the images you're displaying in your recyclerView are large in size and they are not scaled to the size of the imageview before they are displayed
For scaling your images properly using Picasso you can use the .fit() method in Picasso
eg
Or Instead of Picasso you can use Glide
eg
You can also increase the default memory assigned to your app by enabling large heap in your Manifest
eg
For more on Scaling Images and loading Images you can check this link out : https://developer.android.com/training/displaying-bitmaps/load-bitmap.html