在 recyclerview 中显示来自服务器的数据时无休止的滚动

Posted

技术标签:

【中文标题】在 recyclerview 中显示来自服务器的数据时无休止的滚动【英文标题】:Endless scrolling when showing data from server in recyclerview 【发布时间】:2018-11-26 01:31:00 【问题描述】:

我有一个图像应用程序。它从服务器和数据库加载图像。当用户单击特定按钮应用程序时,使用 volley 向服务器发送带有发布数据(类别)的请求。 服务器比获取 post 变量并从数据库中获取数据并将数据作为 json 响应发送。然后我在recyclerview 中显示图像。

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
    imagelist = new ArrayList<>();
    adapter = new ImageAdapter(DJPhotos.this, imagelist);

    RecyclerView.LayoutManager mLayoutManager = new 
    LinearLayoutManager(getApplicationContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setAdapter(adapter);

    public void getJsonResponsePost() 

    JSONObject json = new JSONObject();
    try 
        json.put("table", table);
     catch (JSONException e) 
        e.printStackTrace();
    

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, script, json,
            new Response.Listener<JSONObject>() 
                @Override
                public void onResponse(JSONObject response) 

                    imagelist.clear();
                    JSONArray heroArray = null;
                    try 
                        heroArray = response.getJSONArray("item");
                        for (int i = 0; i < heroArray.length(); i++) 
                            JSONObject jsonObject = heroArray.getJSONObject(i);

                            Photos photos = new Photos();
                            photos.setUrl(jsonObject.getString("image"));
                            photos.setThumb(jsonObject.getString("thumb"));
                            imagelist.add(photos);

                        
                     catch (JSONException e) 
                        e.printStackTrace();
                    

                    adapter.notifyDataSetChanged();

                
            , new Response.ErrorListener() 
        @Override
        public void onErrorResponse(VolleyError error) 
            Log.d(TAG, "Error: " + error.getMessage());

        
    );
    jsonObjectRequest.setTag(REQ_TAG);
    jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
            0,
            DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
            DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    MySingleton.getInstance().addToRequestQueue(jsonObjectRequest);


我的 PHP 脚本 -

 $sql = "select * from $table  WHERE (dp='1') ORDER BY id DESC LIMIT 10";
 $query = mysqli_query($db, $sql);
 $post_data_array = array();
 while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)) 
         $img     = $row['image'];
         $post_data_array[] = array(
                 'image' => $image
            );
 $post_data = json_encode(array('item' => $post_data_array));
 echo $post_data;

数据库中有很多图像,如果我没有设置限制,那么服务器需要时间来获取数据。它使应用程序变慢。 我有一个使用分页的网站。在分页中,我使用 LIMIT 来显示数据。 现在我希望当用户单击按钮时,仅加载数据库中的前 10 张图像,并且在用户滚动 recyclerview 后,应加载另外 10 张图像并继续。

我知道可以用AsyncTask 完成,但我没有找到任何符合我情况的脚本。

【问题讨论】:

【参考方案1】:

我知道可以用 AsyncTask 来完成

这是有史以来最糟糕的方法,不要这样做。

android 现在提供了一个原生分页库作为 Android 架构组件的一部分,使用它阅读更多关于它的信息here。在这种方法之前,人们习惯使用 onScrollChangedListener 设置为回收器视图,您仍然可以使用它,但建议使用分页库。

【讨论】:

如何实现? 如您在此处所建议的那样,要在 android 中使用分页库,服务器端页面是否也应该分页。例如:如果我得到 700 多个数据作为列表并且我只传递了 2 个参数:Token 和 UserId。然后,分页库会工作吗?还是Server php页面必须分页? 没有后端分页,android的分页库就是网络垃圾? 理想情况下,体验会很流畅,但如果您必须在本地完成,您需要下载所有 700 多个结果(由于 UI 被阻止,应用程序中的等待时间会增加)并在本地加载项目,这是不推荐的【参考方案2】:

在适配器上

为例如创建一个这样的界面

public interface OnFetchMoreRequested 
    void fetchMore();

然后 onBindViewHolder 您可以根据您的条件触发该接口,例如

@Override
public void onBindViewHolder(@NonNull final RecipeViewHolder holder, int position) 
    if(position == imagelist.size() - 1 && onFetchMoreRequested != null)
        onFetchMoreRequested.fetchMore();
    
    ... rest of the code

还为OnFetchMoreRequested 接口创建一个setter 和一个字段

OnFetchMoreRequested onFetchMoreRequested = null;

public void setOnFetchMoreRequested(OnFetchMoreRequested onFetchMoreRequested)
    this.onFetchMoreRequested = onFetchMoreRequested;

关于活动

adapter.setOnFetchMoreRequested(new OnFetchMoreRequested() 
    @Override
    void fetchMore()
        ... Go ahead and call your server 
    
);

【讨论】:

以上是关于在 recyclerview 中显示来自服务器的数据时无休止的滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 的 RecyclerView 中显示来自 Firestore 的数据?

kotlin 在片段中的 RecyclerView 中显示来自 Firebase 数据库的数据

我如何使用来自firebase的数据制作recyclerview,并有意图地点击

Cant Firebase 在单个 RecyclerView 中显示来自多个引用的数据

在后台在 Recyclerview 中显示 Coverart(来自 id3)

使用 AsyncTask 在 Fragment 的 RecyclerView 中显示来自 json 的数据?