web-dev-qa-db-ja.com

スクロールが終了する前にRecyclerviewがスムーズにスクロールしない

スクロールに問題があります。つまり、scroolは高速ですが、スクロールが終了する前に遅れているように見えます。ここで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"
        />

編集また、同じフラグメントに下部のナビゲーションバーがあり、スクロールすると表示されます

編集2ここにビデオがあります リンク ラグを示しています
私はすべての解決策を試しましたが、誰も助けてくれませんでした。すべてのコードを追加しました。何か助けてください。

9

コードに問題はありませんでした。まだ以下の点を考慮する必要があります。

(1)APIから取得しているimageのサイズが大きすぎるであるとどうなる可能性がありますか。 APIのサイズを確認し、最大200kb削減します。 (100〜150 kbでも十分です)。

(2)あなたキャッシュを無効にしないでください画像をキャッシュに保存することでユーザーエクスペリエンスを向上させ、次回はURLではなくキャッシュでロードします。

(3)あなた今すぐAndroidで利用できる単純な波及効果のためにmaterial-rippleライブラリを使用する必要はありません。この属性をImageView

 Android:background="?attr/selectableItemBackground"

(4)一度にロードするアイテムの数を確認します。一度に多くのアイテムをロードしないでください。 アーキテクチャコンポーネントページングライブラリ を参照してください

(5)love_gray_iconのようなリソースのサイズも確認してください。最大だと思います70 * 7。それよりも大きい場合は、サイズを変更する必要があります。 一度に複数の画像のサイズを変更する 。また、使用前に画像を圧縮すると、画像サイズが最大80%減少します。サイズ変更後、 画像を圧縮

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

画像が大きすぎることが原因である可能性があります

グライドのようにサイズを変更できます

Glide.with(context)
    .load(imgUrl)
    .diskCacheStrategy(DiskCacheStrategy.ALL)
    .error(placeholder)
    .placeholder(placeholder)
    .dontTransform()
    .override(200,200)
    .into(imageView);
3
Riddhi Shankar

次のようにコードを最適化できます。

@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)呼び出しは毎回メモリにコストがかかるため、アダプタをトラバースする場合にのみ変数を使用するようにしてください。

1
Seeya

スクロールの問題は、バインド中に画像をリロードしていることが原因である可能性があると思います。写真の読み込み中、そしてもちろんページネーション中にキャッシュを使用できます。

1
Anu Bhalla

私はあなたにいくつかの改善提案があります。

  • リストアイテムにロードしている画像が多すぎます。画像の読み込みを可能な限り減らします。たとえば、アプリケーションで通常は変更されない「いいね」や「共有」ボタンのデフォルトの画像を設定することを検討できます。リストアイテムのレイアウトで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の画像検索についても同様のプロジェクトが行われていると思います。 ここGithubのプロジェクト を見つけるかもしれません。

お役に立てば幸いです。

1
Reaz Murshed

recyclerviewのアイテムが同じサイズの場合は、次のことを試すことができます。recyclerview.setHasFixedSize(true);

0
TieuNhi