amodkanthe
amodkanthe

Reputation: 4530

Recyclerview lag in scroll

I am using Recyclerview Gridlayout and I am facing lag while scroll.

Since I am using RecyclerView.Adapter ViewHolder is already there.

Other than that there are no conditions in onBindViewHolder i.e. onCreateView method.

Also I am making sure new objects are not created.

I am using Universal imageloader and I am pausing recyclerview imageloader on scroll as well.

I found that Image size on disk memory varies from 50 to 300 kb aprox is that have something to do with scroll speed?

public class DealsRecyclerAdapter extends RecyclerView.Adapter<DealsRecyclerAdapter.ViewHolder> {
public ArrayList<DealItem> items = new ArrayList<DealItem>();
Context context;
DisplayImageOptions options;
protected ImageLoader imageLoader;
DealItemOnClickListener dealItemOnClickListener;

private static final String RESULTS = "results";

int layoutId;
DealItem item;
String storeName;
public static final String RS = "Rs.";
public static final String AVAIL_FROM = "available from ";
public static final String OFF = "% off";

static class ViewHolder extends RecyclerView.ViewHolder {

    protected TextView itemName;
    protected TextView itemPriceOrig;
    protected TextView itemDisc;
    protected TextView itemPrice;
    protected ImageView itemImage;
    protected TextView itemStore;
    protected TextView itemSpecialText;


    public ViewHolder(View itemView) {
        super(itemView);
        itemImage = (ImageView) itemView
                .findViewById(R.id.logo);
        itemName = ((CustomTextView) itemView
                .findViewById(R.id.title_product_search));
        itemPriceOrig = ((CustomTextView) itemView
                .findViewById(R.id.price_product_orig));
        itemDisc = ((CustomTextView) itemView
                .findViewById(R.id.product_disc));
        itemPrice = ((CustomTextView) itemView
                .findViewById(R.id.price_product));
        itemStore = (TextView) itemView
                .findViewById(R.id.prod_store);
        itemSpecialText = (TextView) itemView
                .findViewById(R.id.tvspecial);
         itemPriceOrig.setPaintFlags(itemPriceOrig
                .getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);                

    }

}

public DealsRecyclerAdapter(Context context, JSONObject jsonObject, int layoutId) {
    try {
        this.layoutId = layoutId;
        this.context = context;
        dealItemOnClickListener = (DealItemOnClickListener) (context);
        options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.load)
                .showImageForEmptyUri(R.drawable.load)
                .showImageOnFail(R.drawable.notfound)
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .considerExifParams(true)
                .resetViewBeforeLoading(true)
                .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                .build();

        imageLoader = ImageLoader.getInstance();

        JSONArray jsonArray = jsonObject.getJSONArray(RESULTS);
        for (int i = 0; i < jsonArray.length(); i++) {
            try {
                items.add(Utils.getdealIemFromJson(jsonArray.getJSONObject(i)));

            } catch (Exception e) {
            }

        }

    } catch (Exception e) {
    }

}

public void add(DealItem item) {
    items.add(item);
}

@Override
public int getItemCount() {
    return items.size();
}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
    v.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (dealItemOnClickListener != null)
                dealItemOnClickListener.dealItemClicked(view);
        }
    });
    ViewHolder vh = new ViewHolder(v);
    return vh;
}

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {

    item = (DealItem) items.get(position);

    holder.itemDisc.setText("(" + (int) Math.abs(item.discount) + OFF + ")");
    holder.itemPriceOrig.setText(RS + item.originalPrice);
    holder.itemPriceOrig.setVisibility(item.priceVisiblity);
    holder.itemDisc.setVisibility(item.discountVisiblity);
    holder.itemPrice.setText(RS + item.dealPrice);
    storeName = AVAIL_FROM + "<b>" + item.store + "</b>";
    holder.itemStore.setText(Html.fromHtml(storeName));
    holder.itemName.setText(item.title);
    holder.itemSpecialText.setText(item.specialText);
    holder.itemSpecialText.setVisibility(item.specialTextVisibility);
    imageLoader.displayImage(item.imageUrl, holder.itemImage, options);
    holder.itemView.setTag(item);
}

@Override
public long getItemId(int arg0) {

    return 0;
}

public interface DealItemOnClickListener {
    void dealItemClicked(View view);
}

public void setLayoutId(int layoutId) {
    this.layoutId = layoutId;
}

}

Upvotes: 4

Views: 10631

Answers (2)

Royi Benyossef
Royi Benyossef

Reputation: 759

Both runtime scaling and image size can have an impact. runtime scaling is usually discouraged and image sizes directly impacts how much could be cached at any one time.

I would also join @Alireza's question and would add a question; if you comment off the image loading is it ok?

I would also refer you to what i believe are better 3rd party image loading libraries such as Fresco, Glide and Picasso who i have a lot of experience with and can vouch for their efficiency.

And last but certainly not least i would invite you to view a session given by a friend of mine called Ran Nachmany where he explains how to analyze such issues with overdraw, systrace and other tools here.

Goodluck.

Upvotes: 8

Alireza Ahmadi
Alireza Ahmadi

Reputation: 5338

I read your code carefully, The only line that seems to make problem is this

    imageLoader.displayImage(item.imageUrl, holder.itemImage, options);

I didn't work with UniversalImageLoader. Does it handles image loading in seprate thread?

any way you can simply make sure if this line is making problem by putting this exact images in resource directory and using imageView.setImageResource to see if you still have problem or not.

In case i'm right and UniversalImageLoader makes your app slow you can create an AsyncTask and run this line in separate thread or perhaps using another image loading library like Picaso.

The next candidate to cause problem is images. 300K may be low but if you sum up images sizes you get magabytes of memory usage which is enough to cause problem in even best android devices. (Android memory monitor is a really useful tool here!) and also some image formats like .jpg use compression to reduce the size and this makes decompressing file slower. Solution for that is photoshop, simply create new photo and copy and past the existing one and save. default options are ok most of the times!

And one final thought about unrelated matter! I see your handling jsonObject in adapter which is not a good practice. Puting is code inside your activity/fragment or better in some Network utility class would be a lot better.

Sorry if i can't be any more help. good luck

Upvotes: 3

Related Questions