为什么RecyclerView会在滚动时始终创建项目

时间:2015-09-03 09:54:41

标签: android android-recyclerview

我使用RecyclerView并且有些不好让我想到为什么RecyclerView会在滚动时始终创建项目?

如果我垂直滚动,我的RecyclerView项目将被重新创建,但它总是发生但不正确,因为项目已经创建,并且在适配器未更改时不会重新创建,对吧?

注意:我使用的是Volley和Picasso。它们都将首次获取图像,当我滚动列表时,它们将删除它们并立即将它们放回去。

我的RecyclerView

public class PersonTimelineAdapter extends UltimateViewAdapter<PersonTimelineAdapter.CellFeedViewHolder>
        implements View.OnClickListener {

    private static final DecelerateInterpolator DECCELERATE_INTERPOLATOR = new DecelerateInterpolator();
    private static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
    private static final OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(4);

    private final Context context;
    private final List<CompactPost> mPosts;

    private OnFeedItemClickListener onFeedItemClickListener;

    private final Map<RecyclerView.ViewHolder, AnimatorSet> likeAnimations = new HashMap<>();
    private final ArrayList<Integer> likedPositions = new ArrayList<>();
    private final String mCurrentProfileId = Logged.Models.getUserProfile().getId().toString();

    public PersonTimelineAdapter(Context context, List<CompactPost> postList) {
        this.context = context;
        mPosts = postList;
    }

    @Override
    public CellFeedViewHolder getViewHolder(View view) {
        return new CellFeedViewHolder(view, false);
    }

    @Override
    public CellFeedViewHolder onCreateViewHolder(ViewGroup viewGroup) {
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.fragment_person_profile_timeline, viewGroup,
                        false);
        CellFeedViewHolder cellFeedViewHolder = new CellFeedViewHolder(view, true);

        cellFeedViewHolder.btnComments.setOnClickListener(this);
        cellFeedViewHolder.btnMore.setOnClickListener(this);
        cellFeedViewHolder.postPicture.setOnClickListener(this);
        cellFeedViewHolder.likeImageButton.setOnClickListener(this);
        cellFeedViewHolder.profilePicture.setOnClickListener(this);
        cellFeedViewHolder.likesContainer.setOnClickListener(this);

        return cellFeedViewHolder;
    }

    @Override
    public void onBindViewHolder(CellFeedViewHolder viewHolder, int
            position) {
        bindFeedItem(position, viewHolder);
    }

    private void setPostPicture(CompactPost post, CellFeedViewHolder holder) {
        String imagePath = Constants.General.PROTOCOL + post.getImageAddress();

        ImageLoader imageLoader = MyApplication.getInstance().getImageLoader();
        holder.postPicture.setImageUrl(imagePath, imageLoader);
    }

    private void setProfilePicture(CompactPost post, final CellFeedViewHolder holder) {
        String imagePath = Constants.General.PROTOCOL + post.getSender().getImageAddress();

        Cache cache = MyApplication.getInstance().getRequestQueue().getCache();
        Cache.Entry entry = cache.get(imagePath);
        if (entry != null) {
            Bitmap bitmap = BitmapFactory.decodeByteArray(entry.data, 0, entry.data.length);
            holder.profilePicture.setImageBitmap(bitmap);
        } else {
            ImageLoader imageLoader = MyApplication.getInstance().getImageLoader();

            imageLoader.get(imagePath, new ImageLoader.ImageListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                }

                @Override
                public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
                    if (response.getBitmap() != null) {
                        holder.profilePicture.setImageBitmap(response.getBitmap());
                    }
                }
            });
        }
    }

    private void bindFeedItem(int position, final CellFeedViewHolder holder) {
        CompactPost item = mPosts.get(position);
        holder.nameTextView.setText(item.getSender().getName());

        int likesCount = item.getLikes().size();
        holder.likesTextView.setText(Integer.toString(likesCount));

        if (item.getSender().getImageAddress() != null) {
            setProfilePicture(item, holder);
        }
        holder.profilePicture.setTag(item.getSender());

        holder.postDateTime.setText(Utils.getTimeAgo(Utils.stringToDate(context, item
                .getInsertTime())
                .getTime()));

        if (item.getImageAddress() != null) {
            holder.videoCC.setVisibility(View.GONE);

            setPostPicture(item, holder);
            holder.imageCC.setVisibility(View.VISIBLE);
            holder.postPictureContainer.setVisibility(View.VISIBLE);
        } else if (item.getVideoAddress() != null) {
            //IMPLEMENT add video
            holder.imageCC.setVisibility(View.GONE);
            String videoPath = Constants.General.PROTOCOL + item.getVideoAddress();
            //holder.videoView.setScaleType(TextureVideoView.ScaleType.CENTER_CROP);
            holder.videoView.setDataSource(context, Uri.parse(videoPath));
            holder.videoView.play();

            holder.videoCC.setVisibility(View.VISIBLE);
            holder.postPictureContainer.setVisibility(View.VISIBLE);
        }
        // No video and no Image
        else {
            holder.postPictureContainer.setVisibility(View.GONE);
        }

        holder.btnComments.setTag(item);

        if (!item.getText().isEmpty()) {
            holder.postTextTextView.setText(item.getText());
            holder.postTextTextView.setVisibility(View.VISIBLE);
        }

        holder.likesTextView.setText(Integer.toString(item.getLikes().size()));

        holder.footerContainer.setTag(item);

        holder.btnMore.setTag(item.getId() + "," + position);

        Hashtable<CellFeedViewHolder, CompactPost> hashtagPost = new Hashtable<>();
        hashtagPost.put(holder, item);
        holder.postPicture.setTag(hashtagPost);

        Hashtable<CellFeedViewHolder, String> hashtableTag = new Hashtable<>();
        hashtableTag.put(holder, "false");
        holder.likeImageButton.setTag(hashtableTag);

        if (item.getLikes().contains(mCurrentProfileId)) {
            hashtableTag.put(holder, "true");
            holder.likeImageButton.setTag(hashtableTag);
            holder.likeImageButton.setImageResource(R.drawable.ic_heart);
        } else {
            holder.likeImageButton.setImageResource(R.drawable.ic_heart_outline);
        }

        holder.likesContainer.setTag(item.getId());

        if (likeAnimations.containsKey(holder)) {
            likeAnimations.get(holder).cancel();
        }
        resetLikeAnimationState(holder);
    }

    @Override
    public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup viewGroup) {
        return null;
    }

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

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder viewHolder, int i) {

    }

    @Override
    public int getAdapterItemCount() {
        return mPosts.size();
    }

    @Override
    public long generateHeaderId(int i) {
        return 0;
    }

    private void updateHeartButton(final CellFeedViewHolder holder, boolean animated) {
        if (animated) {
            if (!likeAnimations.containsKey(holder)) {
                AnimatorSet animatorSet = new AnimatorSet();
                likeAnimations.put(holder, animatorSet);

                ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(holder.likeImageButton, "rotation", 0f, 360f);
                rotationAnim.setDuration(300);
                rotationAnim.setInterpolator(ACCELERATE_INTERPOLATOR);

                ObjectAnimator bounceAnimX = ObjectAnimator.ofFloat(holder.likeImageButton, "scaleX", 0.2f, 1f);
                bounceAnimX.setDuration(300);
                bounceAnimX.setInterpolator(OVERSHOOT_INTERPOLATOR);

                ObjectAnimator bounceAnimY = ObjectAnimator.ofFloat(holder.likeImageButton, "scaleY", 0.2f, 1f);
                bounceAnimY.setDuration(300);
                bounceAnimY.setInterpolator(OVERSHOOT_INTERPOLATOR);
                bounceAnimY.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        holder.likeImageButton.setImageResource(R.drawable.ic_heart);
                    }
                });

                animatorSet.play(rotationAnim);
                animatorSet.play(bounceAnimX).with(bounceAnimY).after(rotationAnim);

                animatorSet.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        resetLikeAnimationState(holder);
                    }
                });

                animatorSet.start();
            }
        } else {
            if (likedPositions.contains(holder.getPosition())) {
                holder.likeImageButton.setImageResource(R.drawable.ic_heart);
            } else {
                holder.likeImageButton.setImageResource(R.drawable.ic_heart_outline);
            }
        }
    }

    public void setOnFeedItemClickListener(OnFeedItemClickListener onFeedItemClickListener) {
        this.onFeedItemClickListener = onFeedItemClickListener;
    }

    private void likePost(final CellFeedViewHolder holder, final CompactPost post) {

        updateLikesCount(holder);

        HttpClient.get(String.format(Constants.Server.GET_POST_LIKE, post.getId(),
                mCurrentProfileId), new
                AsyncHttpResponseHandler() {
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                        CompactPost newPost = GsonParser.getObjectFromGson(responseBody, CompactPost.class);
                        updatePostsObject(post, newPost);
                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                        Toast.makeText(context, context.getString(R.string.toast_error_like),
                                Toast.LENGTH_SHORT)
                                .show();
                        updateUnlikes(holder);
                    }
                });
    }

    private void updateLikesCount(final CellFeedViewHolder holder) {
        int likesCount = Integer.parseInt(holder.likesTextView
                .getText().toString()) + 1;
        holder.likesTextView.setText(Integer.toString(likesCount));
        updateHeartButton(holder, true);
        Hashtable<CellFeedViewHolder, String> hashTags = new Hashtable<>();
        hashTags.put(holder, "true");
        holder.likeImageButton.setTag(hashTags);
        holder.likeImageButton.setImageResource(R.drawable.ic_heart);
    }

    private void updateUnlikes(final CellFeedViewHolder holder) {
        int likesCount = Integer.parseInt(holder.likesTextView
                .getText().toString()) - 1;
        holder.likesTextView.setText(Integer.toString(likesCount));
        holder.likeImageButton.setImageResource(R.drawable.ic_heart_outline);
        Hashtable<CellFeedViewHolder, String> hashTags = new Hashtable<>();
        hashTags.put(holder, "false");
        holder.likeImageButton.setTag(hashTags);
    }

    private void updatePostsObject(CompactPost oldPost, CompactPost newPost) {
        int postId = mPosts.indexOf(oldPost);
        mPosts.add(postId, newPost);
    }

    private void unlikePost(final CellFeedViewHolder holder, final CompactPost post) {

        updateUnlikes(holder);

        HttpClient.get(String.format(Constants.Server.GET_POST_UNLIKE, post.getId()
                , mCurrentProfileId), new
                AsyncHttpResponseHandler() {
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                        CompactPost newPost = GsonParser.getObjectFromGson(responseBody, CompactPost.class);
                        updatePostsObject(post, newPost);
                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                        Toast.makeText(context, context.getString(R.string.toast_error_like),
                                Toast.LENGTH_SHORT)
                                .show();
                        updateLikesCount(holder);
                    }
                });
    }

    @Override
    public void onClick(final View view) {
        switch (view.getId()) {
            case R.id.image_button_comments:
                CompactPost post = (CompactPost) view.getTag();
                if (onFeedItemClickListener != null) {
                    onFeedItemClickListener.onCommentsClick(view, post);
                }
                break;
            case R.id.image_button_more:
                String tag = (String) view.getTag();
                String[] splittedTags = tag.split(",");
                String postId = splittedTags[0];
                int position = Integer.parseInt(splittedTags[1]);
                if (onFeedItemClickListener != null) {
                    onFeedItemClickListener.onMoreClick(view, postId, position);
                }
                break;
            case R.id.image_button_like_small:
                CompactPost post2 = (CompactPost) ((LinearLayout) view.getParent()).getTag();
                final Hashtable hashTags = (Hashtable<CellFeedViewHolder, String>) view
                        .getTag();
                CellFeedViewHolder holder = (CellFeedViewHolder) hashTags.keys().nextElement();
                String isLiked = (String) hashTags.values().iterator().next();
                if (isLiked.equals("false")) {
                    likePost(holder, post2);
                } else {
                    unlikePost(holder, post2);
                }
                break;
            case R.id.image_view_post_picture:
                final Hashtable postPictureTags = (Hashtable<CellFeedViewHolder, Post>) view
                        .getTag();
                CellFeedViewHolder postPictureHolder = (CellFeedViewHolder) postPictureTags.keys()
                        .nextElement();
                CompactPost postPicturePost = (CompactPost) postPictureTags.values()
                        .iterator()
                        .next();
                Hashtable<CellFeedViewHolder, String> btnLikeTags = (Hashtable<CellFeedViewHolder, String>) postPictureHolder
                        .likeImageButton.getTag();

                if (btnLikeTags.values().iterator().next().equals("false")) {
                    animatePhotoLike(postPictureHolder);
                    likePost(postPictureHolder, postPicturePost);
                }
                break;
            case R.id.linear_layout_post_likes:
                postId = (String) view.getTag();
                if (onFeedItemClickListener != null) {
                    onFeedItemClickListener.onLikesCountClick(postId);
                }
                break;

            case R.id.image_view_picture:
                if (onFeedItemClickListener != null) {
                    CompactProfile profile = (CompactProfile) view.getTag();
                    onFeedItemClickListener.onProfileClick(profile);
                }
                break;
        }
    }

    private void animatePhotoLike(final CellFeedViewHolder holder) {
        holder.vBgLike.setVisibility(View.VISIBLE);
        holder.ivLike.setVisibility(View.VISIBLE);

        holder.vBgLike.setScaleY(0.1f);
        holder.vBgLike.setScaleX(0.1f);
        holder.vBgLike.setAlpha(1f);
        holder.ivLike.setScaleY(0.1f);
        holder.ivLike.setScaleX(0.1f);

        AnimatorSet animatorSet = new AnimatorSet();

        ObjectAnimator bgScaleYAnim = ObjectAnimator.ofFloat(holder.vBgLike, "scaleY", 0.1f, 1f);
        bgScaleYAnim.setDuration(200);
        bgScaleYAnim.setInterpolator(DECCELERATE_INTERPOLATOR);
        ObjectAnimator bgScaleXAnim = ObjectAnimator.ofFloat(holder.vBgLike, "scaleX", 0.1f, 1f);
        bgScaleXAnim.setDuration(200);
        bgScaleXAnim.setInterpolator(DECCELERATE_INTERPOLATOR);
        ObjectAnimator bgAlphaAnim = ObjectAnimator.ofFloat(holder.vBgLike, "alpha", 1f, 0f);
        bgAlphaAnim.setDuration(200);
        bgAlphaAnim.setStartDelay(150);
        bgAlphaAnim.setInterpolator(DECCELERATE_INTERPOLATOR);

        ObjectAnimator imgScaleUpYAnim = ObjectAnimator.ofFloat(holder.ivLike, "scaleY", 0.1f, 1f);
        imgScaleUpYAnim.setDuration(300);
        imgScaleUpYAnim.setInterpolator(DECCELERATE_INTERPOLATOR);
        ObjectAnimator imgScaleUpXAnim = ObjectAnimator.ofFloat(holder.ivLike, "scaleX", 0.1f, 1f);
        imgScaleUpXAnim.setDuration(300);
        imgScaleUpXAnim.setInterpolator(DECCELERATE_INTERPOLATOR);

        ObjectAnimator imgScaleDownYAnim = ObjectAnimator.ofFloat(holder.ivLike, "scaleY", 1f, 0f);
        imgScaleDownYAnim.setDuration(300);
        imgScaleDownYAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
        ObjectAnimator imgScaleDownXAnim = ObjectAnimator.ofFloat(holder.ivLike, "scaleX", 1f, 0f);
        imgScaleDownXAnim.setDuration(300);
        imgScaleDownXAnim.setInterpolator(ACCELERATE_INTERPOLATOR);

        animatorSet.playTogether(bgScaleYAnim, bgScaleXAnim, bgAlphaAnim, imgScaleUpYAnim, imgScaleUpXAnim);
        animatorSet.play(imgScaleDownYAnim).with(imgScaleDownXAnim).after(imgScaleUpYAnim);

        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                resetLikeAnimationState(holder);
            }
        });
        animatorSet.start();
    }

    private void resetLikeAnimationState(CellFeedViewHolder holder) {
        likeAnimations.remove(holder);
        holder.vBgLike.setVisibility(View.GONE);
        holder.ivLike.setVisibility(View.GONE);
    }

    public interface OnFeedItemClickListener {
        void onCommentsClick(View v, CompactPost post);

        void onMoreClick(View view, String postId, int position);

        void onProfileClick(CompactProfile profile);

        void onLikesCountClick(String postId);
    }

    public static class CellFeedViewHolder extends UltimateRecyclerviewViewHolder {
        @Bind(R.id.image_view_post_picture)
        NetworkImageView postPicture;
        @Bind(R.id.image_button_comments)
        ImageButton btnComments;
        @Bind(R.id.image_button_like_small)
        ImageButton likeImageButton;
        @Bind(R.id.image_button_more)
        ImageButton btnMore;
        @Bind(R.id.vBgLike)
        View vBgLike;
        @Bind(R.id.ivLike)
        ImageView ivLike;
        @Bind(R.id.text_view_name)
        TextView nameTextView;
        @Bind(R.id.image_view_picture)
        CircleImageView profilePicture;
        @Bind(R.id.text_view_likes)
        TextView likesTextView;
        @Bind(R.id.linear_layout_footer_container)
        LinearLayout footerContainer;
        @Bind(R.id.squared_frame_layout_post_image_container)
        SquaredFrameLayout postPictureContainer;
        @Bind(R.id.text_view_text)
        TextView postTextTextView;
        @Bind(R.id.linear_layout_post_likes)
        LinearLayout likesContainer;
        @Bind(R.id.text_view_datetime)
        TextView postDateTime;
        @Bind(R.id.image_cc)
        FrameLayout imageCC;
        @Bind(R.id.video_cc)
        FrameLayout videoCC;
        @Bind(R.id.cropTextureView)
        TextureVideoView videoView;

        public CellFeedViewHolder(View view, boolean isItem) {
            super(view);
            if (isItem) {
                ButterKnife.bind(this, view);
                postPicture.setDefaultImageResId(R.drawable.ic_file_image_box_2);
                postPicture.setErrorImageResId(R.drawable.ic_file_image_box_2);
            }
        }
    }
}

2 个答案:

答案 0 :(得分:0)

  

我正在使用RecyclerView,不好的事情让我想到了原因   RecyclerView总是在滚动时创建其项目?

不,不是。 onCreateViewHolder仅为viewType调用一次onBindViewHolder。这意味着视图的对象本身只被创建一次。 Android分配了一些足以完全填满屏幕的View。另一方面,ViewHolder在滚动时被调用。您必须使用此回调将您获得的position参数绑定到Uncaught Error: [$injector:modulerr] Failed to instantiate module fastrankApp due to: Error: [$injector:unpr] Unknown provider: $stateProvider

数据集中包含的数据

答案 1 :(得分:0)

复制自我的评论,因为它很长

例如,如果您检查谷歌市场应用程序,如果向下滚动,然后快速向上滚动,您可以看到图像从空图像视图中淡入。

在内存受限的设备中,你不能只将所有这些视图和图像放在内存中,这就是为什么Picasso,Volley和其他具有可配置大小的内存和磁盘缓存的原因。 如果图像需要太长时间才能“重新出现”,请记住取消对不再需要的每个请求的请求,因为如果向下滚动传递视图并且您开始使用URL X加载图像,则重新使用视图,然后继续向下滚动并且该视图被“抛出”然后再次重新用于另一个数据项然后你应该取消X加载请求以加载新的加载请求,这可能会对图像重新出现所花费的时间产生一些影响图像仍将在新图像之前加载 实际上,因为您使用的NetworkImageView不是必需的,因为does会自动为您提供。{/ p>

只是指出行

 Cache cache = MyApplication.getInstance().getRequestQueue().getCache();
    Cache.Entry entry = cache.get(imagePath);
    if (entry != null) {
        Bitmap bitmap = BitmapFactory.decodeByteArray(entry.data, 0, entry.data.length);
        holder.profilePicture.setImageBitmap(bitmap);
    } 

对我来说似乎是不必要的,因为凌空将首先尝试从cache加载并且只有他们会执行远程请求

您也可以事先请求必要的图像,例如,如果您向下滚动并在索引X处,您可以要求凌空加载图像X + 1,X + 2,X + n以便它们来时进入视图,它们将已经在缓存中