Recyclerview在滚动完成之前无法平稳滚动

时间:2018-07-07 13:30:05

标签: java android android-recyclerview recycler-adapter smooth-scrolling

我在滚动时遇到问题。我的意思是滚动速度很快,但在滚动完成之前似乎滞后了。在这里,我定义了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);

这是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());
}

这是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" />

修改

我在同一Fragment中有一个底部导航栏,它在滚动时显示。

编辑2

这是显示滞后的视频link

编辑3

也许我在测试应用程序时发现了问题。我看到了图表,该应用程序从Ram内存中占用了大约120 MB,但仍然不知道如何解决此问题。

编辑4

InstaPostAdapter

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

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

    // Provide a suitable constructor (depends on the kind of dataset)
    public InstaPostAdapter(List<InstaPostModel> items) {
        this.items = items;
    }

    @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);
    }

    @Override
    public void onViewRecycled(@NonNull ViewHolder holder) {
        super.onViewRecycled(holder);
        Glide.with(context).clear(holder.userPhoto);
        Glide.with(context).clear(holder.photo_content);
        Glide.with(context).clear(holder.bt_comment);
        Glide.with(context).clear(holder.bt_like);
        Glide.with(context).clear(holder.bt_share);
    }

    // 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);
        context = holder.itemView.getContext();
            Glide.with(context)
                    .load(Urls.BASE_URI +items.get(position).getUserPhotoUrl()).thumbnail(0.5f)
                    .apply(new RequestOptions()
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true).dontAnimate()
                    )
                    .into(holder.userPhoto);
            Glide.with(context)
                    .load(Urls.BASE_URI +items.get(position).getPostPhotoUrl()).thumbnail(0.5f)
                    .apply(new RequestOptions()
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true).dontAnimate()
                    )
                    .into(holder.photo_content);
            Glide.with(context)
                    .load(R.mipmap.love_gray_icon).thumbnail(0.5f)
                    .apply(new RequestOptions()
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true).dontAnimate()
                    )
                    .into(holder.bt_like);
            Glide.with(context)
                    .load(R.mipmap.comment_icon).thumbnail(0.5f)
                    .apply(new RequestOptions()
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true).dontAnimate()
                    )
                    .into(holder.bt_comment);
            Glide.with(context)
                    .load(R.mipmap.share_icon).thumbnail(0.5f)
                    .apply(new RequestOptions()
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true).dontAnimate()
                    )
                    .into(holder.bt_share);
            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());
        }
    }
}

这是InstaPostListItem.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/insta_user_photo"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_marginBottom="@dimen/spacing_middle"
        android:layout_marginLeft="@dimen/spacing_large"
        android:layout_marginTop="@dimen/spacing_middle" />

    <TextView
        android:id="@+id/insta_user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/spacing_middle"
        android:layout_marginLeft="@dimen/spacing_middle"
        android:layout_marginStart="@dimen/spacing_middle"
        android:layout_marginTop="@dimen/spacing_middle"
        android:text="Person name"
        android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
        android:textColor="@color/material_grey_800"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@id/insta_user_photo" />

    <com.balysv.materialripple.MaterialRippleLayout
        style="@style/RippleStyleBlack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent">

        <ImageView
            android:id="@+id/insta_bt_more"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:clickable="true"
            android:padding="8dp"
            android:tint="@color/grey_hard"
            app:srcCompat="@drawable/ic_more_gray" />
    </com.balysv.materialripple.MaterialRippleLayout>

    <ImageView
        android:id="@+id/insta_photo_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:maxHeight="250dp"
        android:scaleType="centerCrop"
        android:visibility="visible"
        app:layout_constraintTop_toBottomOf="@id/insta_user_photo" />

    <com.balysv.materialripple.MaterialRippleLayout
        android:id="@+id/insta_bt_like_material"
        style="@style/RippleStyleBlack"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/spacing_middle"
        app:layout_constraintTop_toBottomOf="@+id/insta_photo_content">

        <ImageView
            android:id="@+id/insta_bt_like"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:clickable="true" />
    </com.balysv.materialripple.MaterialRippleLayout>

    <com.balysv.materialripple.MaterialRippleLayout
        android:id="@+id/insta_bt_comment_material"
        style="@style/RippleStyleBlack"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/spacing_middle"
        app:layout_constraintStart_toEndOf="@+id/insta_bt_like_material"
        app:layout_constraintTop_toBottomOf="@+id/insta_photo_content">


        <ImageView
            android:id="@+id/insta_bt_comment"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:clickable="true" />
    </com.balysv.materialripple.MaterialRippleLayout>

    <com.balysv.materialripple.MaterialRippleLayout
        android:id="@+id/insta_bt_share_material"
        style="@style/RippleStyleBlack"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@+id/insta_bt_comment_material"
        app:layout_constraintTop_toBottomOf="@+id/insta_photo_content">


        <ImageView
            android:id="@+id/insta_bt_share"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:clickable="true" />
    </com.balysv.materialripple.MaterialRippleLayout>

    <View
        android:id="@+id/emptyView"
        android:layout_width="match_parent"
        android:layout_height="2px"
        android:layout_marginBottom="@dimen/spacing_medium"
        android:background="@color/grey_soft"
        app:layout_constraintTop_toBottomOf="@+id/insta_bt_share_material" />

    <TextView
        android:id="@+id/insta_post_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="@dimen/spacing_xlarge"
        android:text="Sample text"
        android:textColor="@color/grey_dark"
        android:visibility="visible"
        app:layout_constraintTop_toBottomOf="@+id/emptyView" />
    />

    <com.github.curioustechizen.ago.RelativeTimeTextView
        android:id="@+id/insta_post_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="-"
        android:textAppearance="@style/TextAppearance.AppCompat.Caption"
        android:textColor="@color/grey_medium"
        android:textStyle="normal"
        app:layout_constraintTop_toBottomOf="@+id/insta_post_content" />
    />
</android.support.constraint.ConstraintLayout>

我尝试了所有解决方案,但没有人帮助我。我已经添加了所有代码。有人可以帮忙吗?

6 个答案:

答案 0 :(得分:3)

可能是因为图像太大

您可以使用类似滑行的方式调整其大小

some_func

答案 1 :(得分:1)

我认为滚动问题可能是因为您在绑定时重新加载图像。加载照片时可以使用缓存,当然也可以使用分页。

答案 2 :(得分:1)

您可以按以下方式优化代码

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    final InstaPostModel p = items.get(position);
    context = holder.itemView.getContext();
   setImage(holder.userPhoto, p.getUserPhotoUrl());
   setImage(holder.photo_content, p.getPostPhotoUrl());
   setImage(holder.bt_like, R.mipmap.love_gray_icon);

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

}

private void setImage(ImageView iv, String url)
{
          Glide.with(context)
            .load(Urls.BASE_URI +url).thumbnail(0.5f)
            .apply(new RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true).dontAnimate()
            )
            .into(iv);
}
private void setImage(ImageView iv, int resource)
{
          Glide.with(context)
            .load(resource).thumbnail(0.5f)
            .apply(new RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true).dontAnimate()
            )
            .into(iv);
}

这肯定会减少渲染时的负载。请确保仅在遍历适配器时才使用变量,因为每次调用list.get(position)都会占用更大的内存。

答案 3 :(得分:1)

我没有发现您的代码有任何问题。仍然需要考虑以下几点。

(1)您从API获得的图片的大小太大会发生什么。检查API的大小,并使其最大减少200 kb。 (100-150 kb也足够)。

(2)您不应禁用缓存,因为它会通过将图像存储在缓存中并下次通过缓存而不是通过URL加载来改善用户体验。

(3)您无需使用material-ripple 库即可立即在Android中使用简单的波纹效果。将此属性添加到您的ImageView

 android:background="?attr/selectableItemBackground"

(4)检查一次要加载多少个项目。您不应一次加载很多项目。参见Architecture component paging library

(5)还要检查资源的大小,例如love_gray_icon。我认为最大应该为 70 * 70 。如果大于,则应调整其大小。 Resize multiple images at once。使用前还要压缩图像,这将使图像尺寸减小多达80%。调整大小后,compress images

(6)Glide是一个维护良好的库,因此onViewRecycled是多余的。

最后修改代码。

  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());
    }

答案 4 :(得分:1)

我为您提供了一些改进建议。

  • 您在列表项中加载了太多图像。尽可能减少图像加载。例如,您可以考虑为“喜欢”和“共享”按钮设置默认图像,这些图像通常在您的应用程序中不会更改。在列表项布局中将它们设置为android:src
  • 检查Instagram图片是否太大。您可能会获得一个API以加载平均大小的图像。
  • 使用选择器而不是创建嵌套视图,以在单击列表项中的“喜欢”或“共享”按钮时产生连锁反应。尝试使列表项的布局尽可能简单,并尽量避免嵌套视图层次结构。
  • 从您的适配器中删除onViewRecycled功能,我认为这是不必要的。
  • 使用在构造函数中传递的Context初始化适配器。您不必每次都在onBindViewHodler内获取它。
  • 您不必每次都在RequestOption函数中初始化onBindViewHolder。只需初始化一次,然后在每个Glide图像加载器中使用它即可。
  • 删除按钮,注释和共享图像加载器,并按照前面所述从布局中提供图像作为源。
  • 使用DiskCacheStrategy.ALL来缓存图像,这样就不会在每次打开应用程序或加载RecyclerView时加载图像。

因此,最终的适配器应如下所示。

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());
        }
    }
}

我认为我为Flickr图像搜索完成了一个类似的项目。您可能会找到project here in Github

希望有帮助!

答案 5 :(得分:0)

如果recyclerview中的项目大小相同,则可以尝试: recyclerview.setHasFixedSize(true);