Abdelrahman Ashref
Abdelrahman Ashref

Reputation: 115

How to fix Recyclerview returns same items android

i checked a lot of questions to fix my issue but no success also this will fix a 3 issues for me, a big ones!

I'm parsing my YouTube videos using Gson and Retrofit and it showed successfully but after last results it returns the same items over and over.

Here i call my function used to parse videos..

// NestedScrollView used instead of using
// RecyclerView as NestedScrollView disables
// scroll listeners of recycler so, we use nested.
NestedScrollView nestedScrollView = findViewById(R.id.nested_scrollview);

nestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
    if ((scrollY >= (v.getChildAt(v.getChildCount() - 1).getMeasuredHeight() - v.getMeasuredHeight())) && scrollY > oldScrollY) {
            getJson();
        }
    });

    if (videoList.size() == 0) {
        getJson();
    }
}

And here is my getJson which parse my videos...

// Get Json Data
private void getJson() {
    shimmer.setVisibility(View.VISIBLE);
    // Parsed Url
    String url = YoutubeAPI.BASE_URL + YoutubeAPI.SEARCH + YoutubeAPI.KEY + YoutubeAPI.CHANNNEL_ID + YoutubeAPI.ORDER + YoutubeAPI.MAX_RESULTS + YoutubeAPI.PART;

    if (!nextPageToken.equals("")) {
        // Add page token to new url
        url += (YoutubeAPI.NEXT_PAGE_TOKEN + nextPageToken);
        shimmer.setVisibility(View.GONE);
    }

    if (nextPageToken == null) {
        return;
    }

    Call<YoutubeMain> data = YoutubeAPI.getMainVideo().getYoutube(url);
    data.enqueue(new Callback<YoutubeMain>() {
        @Override
        public void onResponse(Call<YoutubeMain> call, Response<YoutubeMain> response) {
            if (response.errorBody() != null) {
                Log.v("TAG", "onResponse: " + response.errorBody());
                shimmer.setVisibility(View.GONE);
                // Print error code
                Toast.makeText(YoutubeActivity.this, response.errorBody().toString(), Toast.LENGTH_SHORT).show();
            } else {
                YoutubeMain youtubeMain = response.body();
                assert youtubeMain != null;
                videoList.addAll(youtubeMain.getItems());
                adapter.notifyDataSetChanged();
                shimmer.setVisibility(View.GONE);
                // Get nextPageToken to assign it to new url
                if (youtubeMain.getNextPageToken() != null) {
                    nextPageToken = youtubeMain.getNextPageToken();
                }
                // Get creatorName to assign it to author
                if (youtubeMain.getItems().get(0).getSnippet().getChannelTitle() != null) {
                    author.setText(youtubeMain.getItems().get(0).getSnippet().getChannelTitle());
                }
            }
        }

        @Override
        public void onFailure(Call<YoutubeMain> call, Throwable t) {
            shimmer.setVisibility(View.GONE);
            // Print error code
            Toast.makeText(YoutubeActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });
}

this is my adapter...

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

    private List<YoutubeVideo> videoList;
    private final OnYoutubeItemClickListener listener;

    private String formatted_date;

    public YoutubeMainAdapter(Context context, List<YoutubeVideo> videoList, OnYoutubeItemClickListener listener) {
        this.videoList = videoList;
        this.listener = listener;
    }

    class YoutubeHolder extends RecyclerView.ViewHolder {

        ImageView thumbnail;
        TextView title, description, publishedAt;

        YoutubeHolder(@NonNull View itemView) {
            super(itemView);
            thumbnail = itemView.findViewById(R.id.ImageThumb);
            title = itemView.findViewById(R.id.textViewTitle);
            description = itemView.findViewById(R.id.textViewDes);
            publishedAt = itemView.findViewById(R.id.textViewDate);
        }

        public void setData(YoutubeVideo data) {
            String getTitle = data.getSnippet().getTitle();
            String getDescription = data.getSnippet().getDescription();
            String getPublishedAt = format_date(data.getSnippet().getPublishedAt());
            String getThumbnail = data.getSnippet().getThumbnails().getHigh().getUrl();
            title.setText(getTitle);
            description.setText(getDescription);
            publishedAt.setText(getPublishedAt);
            Picasso.get()
                    .load(getThumbnail)
                    .into(thumbnail);
        }

        void bind(final YoutubeVideo item, final OnYoutubeItemClickListener listener) {
            itemView.setOnClickListener(v -> listener.onItemClick(item));
        }

    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_youtube_listitem, parent, false);
        return new YoutubeHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        YoutubeVideo youtubeVideo = videoList.get(position);
        YoutubeHolder youtubeHolder = (YoutubeHolder) holder;
        youtubeHolder.setData(youtubeVideo);
        youtubeHolder.bind(videoList.get(position), listener);
    }

    private String format_date(String publishedAt) {
        try {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
            @SuppressLint("SimpleDateFormat") SimpleDateFormat format = new SimpleDateFormat("dd, MMM yyyy • hh:mm a");
            Date date = dateFormat.parse(publishedAt);
            assert date != null;
            formatted_date = format.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return formatted_date;
    }

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

}

I tried many times to fix it but no success and after checking some questions related to this issues, all answers was for (for loop) with regular Json parsing and no Gson. thanks in advance and i appreciate help.

Upvotes: 0

Views: 51

Answers (1)

Marcos Vasconcelos
Marcos Vasconcelos

Reputation: 18276

Your adapter is correct.

Since you noted: after last results it returns the same items over and over. thats because nextPageToken will return null in the last time and you keep the last reference if (youtubeMain.getNextPageToken() != null) nextPageToken = youtubeMain.getNextPageToken();

You need a condition to stop requesting new pages

Upvotes: 2

Related Questions