Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recyclerview not scrolling smoothly before scrolling finish

i am having problem with scrolling i mean the scrool fast but it's look like lagging before scrolling finish here i define RecyclerView :

RecyclerView recyclerView=fragment.getRecyclerView();
        LinearLayoutManager layoutManager = new LinearLayoutManager(fragment.getActivity(), LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.addItemDecoration(new DividerItemDecoration(fragment.getActivity(), LinearLayoutManager.VERTICAL));
 ArrayList<InstaPostModel> rowListItems=getInstaPostListSample();
        InstaPostAdapter rcAdapter = new InstaPostAdapter(rowListItems);
        recyclerView.setAdapter(rcAdapter);

and here onBindViewHolder

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    final InstaPostModel p = items.get(position);
    context = holder.itemView.getContext();
    Glide.with(context).load(R.mipmap.mee_small).into(holder.userPhoto);
    Glide.with(context).load(R.drawable.post_image).into(holder.photo_content);
    Glide.with(context).load(R.mipmap.love_gray_icon).into(holder.bt_like);
    Glide.with(context).load(R.mipmap.comment_icon).into(holder.bt_comment);
    Glide.with(context).load(R.mipmap.share_icon).into(holder.bt_share);

    holder.userNameTextView.setText(p.getPosterUserName());
    holder.postContent.setText(p.getText());
    holder.post_date.setReferenceTime(p.getDate().getTime());
}

and here RecyclerView.xml

<?xml version="1.0" encoding="utf-8"?>

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/qatar_now_posts_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none"
        tools:context=".uis.fragments.home.QatarNowFragment"
        />

Edit also i have bottom navigation bar in same fragment and it show when scrolling

Edit 2 here is video link showing the lag
i tried all the solution but no one help me. i have added all my code please any help?

like image 901
Mohammad Sommakia Avatar asked Jul 07 '18 13:07

Mohammad Sommakia


4 Answers

I did not see any problem with your code. Still below points need to be considered.

(1) What could happen that size of image you are getting from API is too large. Check size of API and make it reduce by 200 kb max. (100-150 kb will be enough too).

(2) You should not disable cache as it will improve user experience by storing image in cache and load next time by cache not by URL.

(3) You don't need to use material-ripple library for a simple ripple effect available in Android now. Add this attribute to your ImageView

 android:background="?attr/selectableItemBackground"

(4) Check how many items you are loading at once. You should not load many items at once. See Architecture component paging library

(5) Also check size of your resources like love_gray_icon. I think it should be max 70*70. If you have larger than that, you should resize it. Resize multiple images at once. Also compress images before use, that will decrease image size up-to 80%. After resize, compress images.

(6) Glide is an well maintained library so onViewRecycled is redundant.

Finally bit amendment in your code.

  private void loadImage(ImageView iv, String url) {
        Glide.with(iv.getContext()).load(url).thumbnail(0.5f).into(iv);
    }

    private void loadImage(ImageView iv, int resId) {
        Glide.with(iv.getContext()).load(resId).thumbnail(0.5f).into(iv);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final InstaPostModel p = items.get(position);

        loadImage(holder.userPhoto, Urls.BASE_URI + p.getUserPhotoUrl());
        loadImage(holder.photo_content, Urls.BASE_URI + p.getPostPhotoUrl());
        loadImage(holder.bt_like, R.mipmap.love_gray_icon);
        loadImage(holder.bt_comment, R.mipmap.comment_icon);
        loadImage(holder.bt_share, R.mipmap.share_icon);

        holder.userNameTextView.setText(p.getPosterUserName());
        holder.postContent.setText(p.getText());
        holder.post_date.setReferenceTime(p.getDate().getTime());
    }
like image 172
Khemraj Sharma Avatar answered Oct 25 '22 00:10

Khemraj Sharma


It might be because of the images are too big

You can resize it using glide like

Glide.with(context)
    .load(imgUrl)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .error(placeholder)
    .placeholder(placeholder)
    .dontTransform()
    .override(200,200)
    .into(imageView);
like image 24
Riddhi Shankar Avatar answered Oct 24 '22 23:10

Riddhi Shankar


I have several improvement suggestions for you.

  • You are loading too many images in a list item. Reduce the image loading as much as possible. For example, you might consider setting the default images for the like and share button which are not usually changing in your application. Set them as android:src in the list item layout.
  • Check if the Instagram images are too big in size. You might get an API to load an average sized image.
  • Use a selector instead of creating a nested view to have a ripple effect on clicking on your like or share button in the list item. Try to keep the list item layout as simple as possible and try to avoid nested view hierarchy as much as possible.
  • Remove the onViewRecycled function from your adapter which I found unnecessary.
  • Initialize the adapter with the Context passed to it in the constructor. You do not have to get it every time inside your onBindViewHodler.
  • You do not have to initialize the RequestOption each time in your onBindViewHolder function. Just initialize once and use it in each Glide image loader.
  • Remove the button, comment and share image loaders and supply the images there as the source from the layout as stated before.
  • Use DiskCacheStrategy.ALL to cache your images so that it does not load each time you open the application or load the RecyclerView.

Hence, the final adapter should look like this.

public class InstaPostAdapter
        extends RecyclerView.Adapter<InstaPostAdapter.ViewHolder> {

    private List<InstaPostModel> items = new ArrayList<>();
    Context context;

    // Initialize the context once, use it everywhere
    public InstaPostAdapter(List<InstaPostModel> items, Context context) {
        this.items = items;
        this.context = context;
    }

    @Override
    public InstaPostAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.insta_post_list_item, parent, false);
        // set the view's size, margins, paddings and layout parameters
        return new ViewHolder(v);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final InstaPostModel p = items.get(position);
        RequestOptions requestOptions = new RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.ALL);

        Glide.with(context)
                .load(Urls.BASE_URI + items.get(position).getUserPhotoUrl()).thumbnail(0.5f)
                .apply(requestOptions)
                .into(holder.userPhoto);
        Glide.with(context)
                .load(Urls.BASE_URI + items.get(position).getPostPhotoUrl()).thumbnail(0.5f)
                .apply(requestOptions)
                .into(holder.photo_content);

        // Removed the like, comment, share images which should be set from layout.

        holder.userNameTextView.setText(p.getPosterUserName());
        holder.postContent.setText(p.getText());
        holder.post_date.setReferenceTime(p.getDate().getTime());
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void add(InstaPostModel post, int i) {
        items.add(post);
        notifyItemInserted(i);
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public ImageView userPhoto;
        public TextView userNameTextView;
        public ImageView bt_more;
        public ImageView photo_content;
        public ImageView bt_like;
        public ImageView bt_comment;
        public ImageView bt_share;
        public TextView postContent;
        public RelativeTimeTextView post_date;

        public ViewHolder(View v) {
            super(v);
            userPhoto = v.findViewById(R.id.insta_user_photo);
            userNameTextView = v.findViewById(R.id.insta_user_name);
            bt_more = v.findViewById(R.id.insta_bt_more);
            photo_content = v.findViewById(R.id.insta_photo_content);
            bt_like = v.findViewById(R.id.insta_bt_like);
            bt_comment = v.findViewById(R.id.insta_bt_comment);
            bt_share = v.findViewById(R.id.insta_bt_share);
            postContent = v.findViewById(R.id.insta_post_content);
            post_date = v.findViewById(R.id.insta_post_date);
            setClickListener();
        }

        private void setClickListener() {
            bt_more.setOnClickListener(view -> {
                PopupMenu popupMenu = new PopupMenu(context, view);
                popupMenu.setOnMenuItemClickListener(item -> {
                    Snackbar.make(view, item.getTitle() + " Clicked", Snackbar.LENGTH_SHORT).show();
                    return true;
                });
                popupMenu.inflate(R.menu.menu_feed_popup);
                popupMenu.show();
            });
            bt_like.setOnClickListener(view -> Snackbar.make(view, "Like Clicked", Snackbar.LENGTH_SHORT).show());
            bt_comment.setOnClickListener(view -> Snackbar.make(view, "Comment Clicked", Snackbar.LENGTH_SHORT).show());
            bt_share.setOnClickListener(view -> Snackbar.make(view, "Share Clicked", Snackbar.LENGTH_SHORT).show());
        }
    }
}

I think I have a similar project done for Flickr image search. You might find the project here in Github.

Hope that helps!

like image 20
Reaz Murshed Avatar answered Oct 24 '22 23:10

Reaz Murshed


I think scrolling issue might be because you are reloading images while binding. You can use cache while loading photos and of course, Pagination.

like image 41
Anu Bhalla Avatar answered Oct 25 '22 00:10

Anu Bhalla