android - recyclerView.addOnScrollListener - "retrofit pagination with MVVM"正在加载相同的响应/列表

标签 android mvvm android-recyclerview retrofit infinite-scroll

我在我的应用程序中使用博客 API、改造和 MVVM,我尝试在用户滚动时使用分页来加载更多帖子,这里发生的问题是响应正在加载它自己“相同的列表/相同的十个帖子再次加载”
这是我的代码
帖子客户端类

public class PostsClient {

    private static final String TAG = "PostsClient";

    private static final String KEY = "XYZ sensitive key!";
    private static final String BASE_URL = "https://www.googleapis.com/blogger/v3/blogs/4294497614198718393/";

    private PostInterface postInterface;
    private static PostsClient INSTANCE;

    public PostsClient() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        postInterface = retrofit.create(PostInterface.class);

    }

    public static PostsClient getINSTANCE() {
        if(INSTANCE == null){
            INSTANCE = new PostsClient();
        }
        return INSTANCE;
    }



    public Call<PostList> getPostList(){

        return postInterface.getPostList(KEY);
    }



}

[ 后 View 模型 ]
public class PostViewModel extends ViewModel {

    public static final String TAG = "PostViewModel";


    public MutableLiveData<PostList> postListMutableLiveData = new MutableLiveData<>();
    public MutableLiveData<PostList> postListByLabelMutableLiveData = new MutableLiveData<>();
    public MutableLiveData<String> finalURL = new MutableLiveData<>();
    public MutableLiveData<String> token = new MutableLiveData<>();

    public void getPosts(){


        if (token.getValue() != "") {
            finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
        }
        if (token == null) {
            return;
        }

        PostsClient.getINSTANCE().getPostList().enqueue(new Callback<PostList>() {
            @Override
            public void onResponse(@NotNull Call<PostList> call, @NotNull Response<PostList> response) {

                PostList list = response.body();

                if (list.getItems() != null) {
                    token.setValue(list.getNextPageToken());
                    postListMutableLiveData.setValue(list);
                }

                Log.i(TAG,response.body().getItems().toString());
            }

            @Override
            public void onFailure(Call<PostList> call, Throwable t) {
                Log.e(TAG,t.getMessage());
            }
        });

    }


    public void getPostListByLabel(){

        PostsByLabelClient.getINSTANCE().getPostListByLabel(finalURL.getValue()).enqueue(new Callback<PostList>() {
            @Override
            public void onResponse(Call<PostList> call, Response<PostList> response) {
                postListByLabelMutableLiveData.setValue(response.body());
            }

            @Override
            public void onFailure(Call<PostList> call, Throwable t) {

            }
        });
    }
}

HomeFragment 类“主页”
public class HomeFragment extends Fragment {

    private PostViewModel postViewModel;
    public static final String TAG = "HomeFragment";
    private RecyclerView recyclerView;
    private PostAdapter postAdapter;
    private List<Item> itemArrayList;
    private boolean isScrolling = false;
    private int currentItems, totalItems, scrollOutItems, selectedIndex;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        postViewModel = new ViewModelProvider(this).get(PostViewModel.class);
        postViewModel.getPosts();

        View root = inflater.inflate(R.layout.fragment_home, container, false);

        itemArrayList = new ArrayList<>();

        recyclerView = root.findViewById(R.id.homeRecyclerView);
        postAdapter = new PostAdapter(getContext(),itemArrayList);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext()
                , linearLayoutManager.getOrientation());
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.addItemDecoration(dividerItemDecoration);
        recyclerView.setAdapter(postAdapter);

//                textView.setText(s);
                postViewModel.postListMutableLiveData.observe(HomeFragment.this, new Observer<PostList>() {
                    @Override
                    public void onChanged(PostList postList) {
                        itemArrayList.addAll(postList.getItems());
                        postAdapter.notifyDataSetChanged();
                    }
                });


        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                    isScrolling = true;



            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy > 0) {
                    currentItems = linearLayoutManager.getChildCount();
                    totalItems = linearLayoutManager.getItemCount();
                    scrollOutItems = linearLayoutManager.findFirstVisibleItemPosition();
                    if (isScrolling && (currentItems + scrollOutItems == totalItems)) {
                        isScrolling = false;
                        postViewModel.getPosts();
                        postAdapter.notifyDataSetChanged();


                    }
                }

            }
        });


        return root;

    }
}
'更多解释
在 PostViewModel 上
我创建了一个变量public MutableLiveData<String> token = new MutableLiveData<>();这个代表一个新页面/响应的 token 将带有“每个页面都有一个列表/十个新帖子”
在 HomeFragment 上
我创建了三个整数值private int currentItems, totalItems, scrollOutItems, selectedIndex;和一个 bool 值private boolean isScrolling = false;然后我用了recyclerView.addOnScrollListener用这种方式加载接下来的十个帖子,但它不像我之前说的那样工作,它加载相同的结果/列表
The result on imgur.com

最佳答案

经过数百次尝试,我终于解决了,这是问题的解决方案
首先我更改了 GET API 中的方法 PostInterface并让它采取@URL而不是 @Query像这样的KEY

public interface PostInterface {

    @GET
    Call<PostList> getPostList(@Url String URL);
}
中学 我编辑了PostsClientBASE_URL 中删除最终结果private static String BASE_URL并为 创建一个 setter 和 getter基本 URL 和 key
public static String getKEY() {
        return KEY;
    }

    public static String getBaseUrl() {
        return BASE_URL;
    }
第三和最后 我在响应之后为 token 检查器移动了这个 if 语句
public void getPosts(){

        Log.e(TAG,finalURL.getValue());

        PostsClient.getINSTANCE().getPostList(finalURL.getValue()).enqueue(new Callback<PostList>() {
            @Override
            public void onResponse(@NotNull Call<PostList> call, @NotNull Response<PostList> response) {

                PostList list = response.body();


                if (list.getItems() != null) {

                    Log.e(TAG,list.getNextPageToken());
                    token.setValue(list.getNextPageToken());
                    postListMutableLiveData.setValue(list);

                }
                if (token.getValue() == null || !token.getValue().equals("") ) {
                    finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
                }


//                Log.i(TAG,response.body().getItems().toString());
            }

            @Override
            public void onFailure(Call<PostList> call, Throwable t) {
                Log.e(TAG,t.getMessage());
            }
        });

    }

关于android - recyclerView.addOnScrollListener - "retrofit pagination with MVVM"正在加载相同的响应/列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66156640/

相关文章:

android - 我可以在 ViewModel 中使用 view.getContext() 作为我的数据绑定(bind)类吗

javascript - Knockout 如何使用元素获取数据绑定(bind)键和可观察值?

android - 在 RecyclerView 中选择项目时,如何防止 notifyItemChanged() 消除链式 react ?

java - 对 ListActivity 中的 ListView 进行排序

Android VideoView OnCompletionListener 不工作

java - 用于构建多个android项目的脚本

android - VideoView 和 ExoPlayer 之间有什么区别?为什么我会更喜欢其中一个而不是另一个?

c# - 使用 WPF 工具包绑定(bind)饼图不显示点

android - Jetpack compose 中的 [NestedScrollView + RecyclerView] 或 [Nested RecyclerView (Recycler inside another recycler) 相当于什么

android - RecyclerView 不显示列表中的元素