Android 如何修复Recyclerview返回相同的项目

Android 如何修复Recyclerview返回相同的项目,android,android-studio,Android,Android Studio,我检查了很多问题来解决我的问题,但没有成功。这将为我解决3个问题,一个大问题 我正在使用Gson和改型解析我的YouTube视频,它成功地显示了,但在最后的结果之后,它一遍又一遍地返回相同的项目 在这里,我调用用于解析视频的函数 // NestedScrollView used instead of using // RecyclerView as NestedScrollView disables // scroll listeners of recycler so, we use neste

我检查了很多问题来解决我的问题,但没有成功。这将为我解决3个问题,一个大问题

我正在使用Gson和改型解析我的YouTube视频,它成功地显示了,但在最后的结果之后,它一遍又一遍地返回相同的项目

在这里,我调用用于解析视频的函数

// 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();
    }
}
这是我的getJson,它解析我的视频

// 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();
        }
    });
}
//获取Json数据
私有void getJson(){
微光设置可见性(视图可见);
//解析Url
字符串url=YoutubeAPI.BASE\u url+YoutubeAPI.SEARCH+YoutubeAPI.KEY+YoutubeAPI.channel\u ID+YoutubeAPI.ORDER+YoutubeAPI.MAX\u RESULTS+YoutubeAPI.PART;
如果(!nextPageToken.equals(“”){
//将页面标记添加到新url
url+=(YoutubeAPI.NEXT_PAGE_TOKEN+nextPageToken);
微光。设置可见性(视图。消失);
}
if(nextPageToken==null){
返回;
}
Call data=YoutubeAPI.getMainVideo().getYoutube(url);
data.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
if(response.errorBody()!=null){
Log.v(“TAG”,“onResponse:+response.errorBody());
微光。设置可见性(视图。消失);
//打印错误代码
Toast.makeText(YoutubeActivity.this,response.errorBody().toString(),Toast.LENGTH_SHORT.show();
}否则{
YoutubeMain YoutubeMain=response.body();
断言youtubeMain!=null;
videoList.addAll(youtubeMain.getItems());
adapter.notifyDataSetChanged();
微光。设置可见性(视图。消失);
//让nextPageToken将其分配给新url
if(youtubeMain.getNextPageToken()!=null){
nextPageToken=youtubeMain.getNextPageToken();
}
//获取creatorName以将其分配给作者
if(youtubeMain.getItems().get(0.getSnippet().getChannelTitle()!=null){
author.setText(youtubeMain.getItems().get(0.getSnippet().getChannelTitle());
}
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
微光。设置可见性(视图。消失);
//打印错误代码
Toast.makeText(YoutubeActivity.this,t.getMessage(),Toast.LENGTH_SHORT.show();
}
});
}
这是我的适配器

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

}

公共类YoutubeMainAdapter扩展了RecyclerView.Adapter{
私人列表视频列表;
私有最终OnYoutubeItemClickListener监听器;
私有字符串格式的\u日期;
public YoutubeMainAdapter(上下文上下文、列表视频列表、OnYoutubeItemClickListener侦听器){
this.videoList=视频列表;
this.listener=listener;
}
类YoutubeHolder扩展了RecyclerView.ViewHolder{
图像视图缩略图;
文本视图标题、描述、发布数据;
YoutubeHolder(@NonNull View itemView){
超级(项目视图);
缩略图=itemView.findViewById(R.id.ImageThumb);
title=itemView.findviewbyd(R.id.textViewTitle);
description=itemView.findviewbyd(R.id.textViewDes);
publishedAt=itemView.findviewbyd(R.id.textViewDate);
}
公共void setData(YoutubeVideo数据){
字符串getTitle=data.getSnippet().getTitle();
字符串getDescription=data.getSnippet().getDescription();
字符串getPublishedAt=格式\日期(data.getSnippet().getPublishedAt());
字符串getThumbnail=data.getSnippet().getThumbnails().getHigh().getUrl();
title.setText(getTitle);
description.setText(getDescription);
publishedAt.setText(getPublishedAt);
毕加索
.加载(缩略图)
.插入(缩略图);
}
无效绑定(最终YoutubeVideo项,最终OnYoutubeItemClickListener侦听器){
setOnClickListener(v->listener.onItemClick(item));
}
}
@非空
@凌驾
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup父级,int-viewType){
View View=LayoutInflater.from(parent.getContext()).flate(R.layout.activity\u youtube\u listitem,parent,false);
返回新的YoutubeHolder(视图);
}
@凌驾
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder,int位置){
YoutubeVideo YoutubeVideo=videoList.get(位置);
YoutubeHolder YoutubeHolder=(YoutubeHolder)持有人;
setData(youtubeVideo);
bind(videoList.get(position),listener);
}
私有字符串格式\u日期(字符串发布日期){
试一试{
DateFormat DateFormat=新的SimpleDataFormat(“yyyy-MM-dd'HH:MM:ss.SSS'Z',Locale.getDefault());
@SuppressLint(“SimpleDataFormat”)SimpleDataFormat格式=新的SimpleDataFormat(“dd,MMM yyyy•hh:mm a”);
Date-Date=dateFormat.parse(publishedAt);
断言日期!=null;
formatted_date=format.format(日期);
}捕获(解析异常){
e、 printStackTrace();
}
返回日期;
}
@凌驾
public int getItemCount(){
返回videoList.size();
}
}

我尝试了很多次来修复它,但都没有成功,在检查了一些与此问题相关的问题后,所有的答案都是for(for循环),带有常规的Json解析,没有Gson。提前感谢您的帮助。

您的适配器是正确的

因为您注意到:
在上次结果之后,它会一次又一次地返回相同的项。
这是因为
nextpGetOken
将在上次返回
null
,并且如果(youtubeMain.getnextpGetOken()!=null)nextpGetOken=youtubeMain.getnextpGetOken(),您将保留上次引用