如何在RecyclerView中实现setOnScrollListener

当用户到达列表中可见的项目时,如何在底部显示进度条。

我编写了一个代码,我使用Web服务获取数据,现在我想填充部分记录,因为我的JSON中有大约630条记录

这是我用来从JSON获取数据并填充到RecyclerView中的整个代码。

以下是我的JSON外观,但真正的JSON包含600多条记录:

http://walldroidhd.com/api.php 

有人可以指导我在我的代码中进行更改吗?

我想在用户使用进度条滚动到底部时填充更多记录,但我仍然显示所有记录。

RecyclerViewFragment.java:

 public class RecyclerViewFragment extends Fragment { RecyclerView mRecyclerView; LinearLayoutManager mLayoutManager; RecyclerView.Adapter mAdapter; ArrayList actorsList; private int previousTotal = 0; private boolean loading = true; private int visibleThreshold = 5; int firstVisibleItem, visibleItemCount, totalItemCount; public static RecyclerViewFragment newInstance() { return new RecyclerViewFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_recyclerview_advance, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); actorsList = new ArrayList(); new JSONAsyncTask().execute("my JSON url"); mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); mRecyclerView.setHasFixedSize(true); mLayoutManager = new GridLayoutManager(getActivity(), 2); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); visibleItemCount = mRecyclerView.getChildCount(); totalItemCount = mLayoutManager.getItemCount(); firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); if (loading) { if (totalItemCount > previousTotal) { loading = false; previousTotal = totalItemCount; } } if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { // End has been reached Log.i("...", "end called"); // Do something loading = true; } } }); // mAdapter = new CardAdapter(); mAdapter = new RecyclerViewMaterialAdapter(new CardAdapter(getActivity(), actorsList), 2); mRecyclerView.setAdapter(mAdapter); MaterialViewPagerHelper.registerRecyclerView(getActivity(), mRecyclerView, null); mRecyclerView.addOnItemTouchListener( new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(getActivity(), String.valueOf(position), Toast.LENGTH_LONG).show(); } }) ); } class JSONAsyncTask extends AsyncTask { ProgressDialog dialog; @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(getActivity()); dialog.setMessage("Loading, please wait"); dialog.setTitle("Connecting server"); dialog.show(); dialog.setCancelable(false); } @Override protected Boolean doInBackground(String... urls) { try { //------------------>> HttpGet httppost = new HttpGet(urls[0]); HttpClient httpclient = new DefaultHttpClient(); HttpResponse response = httpclient.execute(httppost); // StatusLine stat = response.getStatusLine(); int status = response.getStatusLine().getStatusCode(); if (status == 200) { HttpEntity entity = response.getEntity(); String data = null; try { data = EntityUtils.toString(entity); } catch (IOException e) { e.printStackTrace(); } JSONObject jsono = null; try { jsono = new JSONObject(data); } catch (JSONException e) { e.printStackTrace(); } JSONArray jarray = jsono.getJSONArray("wallpapers"); for (int i = 0; i > } catch (ParseException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return false; } protected void onPostExecute(Boolean result) { dialog.cancel(); mAdapter.notifyDataSetChanged(); if (result == false) { Toast.makeText(getActivity(), "Unable to fetch data from server", Toast.LENGTH_LONG).show(); } else { } } } } 

CardAdapter.java:

 public class CardAdapter extends RecyclerView.Adapter { private ArrayList mItems; private Context mContext; public CardAdapter(Context context, ArrayList feedItemList) { this.mItems = feedItemList; this.mContext = context; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()) .inflate(R.layout.recycler_view_card_item, viewGroup, false); ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { NatureItem nature = mItems.get(i); viewHolder.tvNature.setText(nature.getName()); Picasso.with(mContext).load(nature.getThumbnail()) .error(R.mipmap.ic_launcher) .placeholder(R.mipmap.ic_launcher) .into(viewHolder.imgThumbnail); } @Override public int getItemCount() { return mItems.size(); } class ViewHolder extends RecyclerView.ViewHolder{ public ImageView imgThumbnail; public TextView tvNature; public ViewHolder(View itemView) { super(itemView); imgThumbnail = (ImageView)itemView.findViewById(R.id.img_thumbnail); tvNature = (TextView)itemView.findViewById(R.id.tv_nature); } } } 

这是我如何实现Endless,使用这个 :

 mRecyclerView.setOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) { @Override public void onLoadMore(int current_page) { // do something... } }); 

注意:我个人更喜欢使用RecyclerView onScrollfunction来完成我的工作。

在xml布局文件中具有recylcerview的活动类

 public class WallpaperActivity extends AppCompatActivity implements OnTaskCompleted { private static final String TAG = "WallpaperActivity"; private Toolbar toolbar; private RecyclerView mRecyclerView; private WallPaperDataAdapter mAdapter; private LinearLayoutManager mLayoutManager; // to keep track which pages loaded and next pages to load public static int pageNumber; private List wallpaperImagesList; protected Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.wallpaper_main); toolbar = (Toolbar) findViewById(R.id.toolbar); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); pageNumber = 1; wallpaperImagesList = new ArrayList(); handler = new Handler(); if (toolbar != null) { setSupportActionBar(toolbar); getSupportActionBar().setTitle("WallPapers"); } // use this setting to improve performance if you know that changes // in content do not change the layout size of the RecyclerView mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(this); // use a linear layout manager mRecyclerView.setLayoutManager(mLayoutManager); // create an Object for Adapter mAdapter = new WallPaperDataAdapter(wallpaperImagesList, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); getWebServiceData(); mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore() { //add null , so the adapter will check view_type and show progress bar at bottom wallpaperImagesList.add(null); mAdapter.notifyItemInserted(wallpaperImagesList.size() - 1); ++pageNumber; getWebServiceData(); } }); } public void getWebServiceData() { BackGroundTask backGroundTask = new BackGroundTask(this, this, pageNumber); backGroundTask.execute(); } @Override public void onTaskCompleted(String response) { parsejosnData(response); } public void parsejosnData(String response) { try { JSONObject jsonObject = new JSONObject(response); // String json = jsonObject.toString(); JSONArray jsonArray = jsonObject.getJSONArray("wallpapers"); if (jsonArray != null) { // looping through All albums if (pageNumber > 1) { wallpaperImagesList.remove(wallpaperImagesList.size() - 1); mAdapter.notifyItemRemoved(wallpaperImagesList.size()); } for (int i = 0; i < jsonArray.length(); i++) { JSONObject c = jsonArray.getJSONObject(i); // Storing each json item values in variable String id = c.getString("id"); String orig_url = c.getString("orig_url"); String thumb_url = c.getString("thumb_url"); String downloads = c.getString("downloads"); String fav = c.getString("fav"); // Creating object for each product WallPaper singleWall = new WallPaper(id, orig_url, thumb_url, downloads, fav); // adding HashList to ArrayList wallpaperImagesList.add(singleWall); handler.post(new Runnable() { @Override public void run() { mAdapter.notifyItemInserted(wallpaperImagesList.size()); } }); } mAdapter.setLoaded(); } else { Log.d("Wallpapers: ", "null"); } } catch (JSONException e) { e.printStackTrace(); } } } 

适配器类

 public class WallPaperDataAdapter extends RecyclerView.Adapter { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List imagesList; // The minimum amount of items to have below your current scroll position // before loading more. private int visibleThreshold = 5; private int lastVisibleItem, totalItemCount; private boolean loading; private OnLoadMoreListener onLoadMoreListener; public WallPaperDataAdapter(List imagesList1, RecyclerView recyclerView) { imagesList = imagesList1; if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView .getLayoutManager(); recyclerView .addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager .findLastVisibleItemPosition(); if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { // End has been reached // Do something if (onLoadMoreListener != null) { onLoadMoreListener.onLoadMore(); } loading = true; } } }); } } @Override public int getItemViewType(int position) { return imagesList.get(position) != null ? VIEW_ITEM : VIEW_PROG; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder vh; if (viewType == VIEW_ITEM) { View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.wallpaper_row, parent, false); vh = new WallPaperViewHolder(v); } else { View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.progress_item, parent, false); vh = new ProgressViewHolder(v); } return vh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof WallPaperViewHolder) { WallPaper singleWallPaper = (WallPaper) imagesList.get(position); Glide.with(((WallPaperViewHolder) holder).thumbIcon.getContext()) .load(singleWallPaper.getThumbUrl()) .centerCrop() .placeholder(R.drawable.bg) .crossFade() .into(((WallPaperViewHolder) holder).thumbIcon); } else { ((ProgressViewHolder) holder).progressBar.setIndeterminate(true); } } public void setLoaded() { loading = false; } @Override public int getItemCount() { return imagesList.size(); } public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) { this.onLoadMoreListener = onLoadMoreListener; } // public static class WallPaperViewHolder extends RecyclerView.ViewHolder { public ImageView thumbIcon; public WallPaperViewHolder(View v) { super(v); thumbIcon = (ImageView) v.findViewById(R.id.thumbIcon); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar) v.findViewById(R.id.progressBar1); } } } 

wallpaper_row.xml

     

progress_item.xml

     

单独BackGroundTask.java

 public class BackGroundTask extends AsyncTask { private ProgressDialog pDialog; public OnTaskCompleted listener = null;//Call back interface Context context; int pageNumber; public BackGroundTask(Context context1, OnTaskCompleted listener1, int pageNumber) { context = context1; listener = listener1; //Assigning call back interface through constructor this.pageNumber = pageNumber; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Object... params) { //My Background tasks are written here synchronized (this) { String url = Const.URL_WALLPAPERS_HD + pageNumber; String jsonStr = ServiceHandler.makeServiceCall(url, ServiceHandler.GET); Log.i("Url: ", "> " + url); Log.i("Response: ", "> " + jsonStr); return jsonStr; } } @Override protected void onPostExecute(String result) { super.onPostExecute(result); listener.onTaskCompleted(result); } } 

ServiceHanlder.java

 public class ServiceHandler { static String response = null; public final static int GET = 1; public final static int POST = 2; public ServiceHandler() { } /** * Making service call * * @url - url to make request * @method - http request method */ public static String makeServiceCall(String url, int method) { return makeServiceCall(url, method, null); } /** * Making service call * * @url - url to make request * @method - http request method * @params - http request params */ public static String makeServiceCall(String url, int method, List params) { try { // http client DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null; // Checking http request method type if (method == POST) { HttpPost httpPost = new HttpPost(url); // adding post params if (params != null) { httpPost.setEntity(new UrlEncodedFormEntity(params)); } Log.e("Selltis Request URL", url); httpResponse = httpClient.execute(httpPost); } else if (method == GET) { // appending params to url if (params != null) { String paramString = URLEncodedUtils .format(params, "utf-8"); url += paramString; Log.i("Request URL", url); } HttpGet httpGet = new HttpGet(url); httpResponse = httpClient.execute(httpGet); } httpEntity = httpResponse.getEntity(); response = EntityUtils.toString(httpEntity); } catch (UnsupportedEncodingException e) { e.printStackTrace(); return "Fail"; } catch (ClientProtocolException e) { e.printStackTrace(); return "Fail"; } catch (IOException e) { e.printStackTrace(); return "Fail"; } return response; } } 

加载接口更多

 public interface OnLoadMoreListener { void onLoadMore(); } 

用于了解从asynctask加载的Web服务数据的接口

 public interface OnTaskCompleted{ void onTaskCompleted(String response); } 

如果这有效或有任何问题,请告诉我。 最好使用Volley或okHttp库进行网络连接。

对于ImageLoading,我使用了Glide Library。

这就是我如何检测RecyclerView是否应该由OnScrollListener刷新,看看它:

 recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { int ydy = 0; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int offset = dy - ydy; ydy = dy; boolean shouldRefresh = (linearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0) && (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) && offset > 30; if (shouldRefresh) { //swipeRefreshLayout.setRefreshing(true); //Refresh to load data here. return; } boolean shouldPullUpRefresh = linearLayoutManager.findLastCompletelyVisibleItemPosition() == linearLayoutManager.getChildCount() - 1 && recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && offset < -30; if (shouldPullUpRefresh) { //swipeRefreshLayout.setRefreshing(true); //refresh to load data here. return; } swipeRefreshLayout.setRefreshing(false); } }); 

希望你会受到启发。 祝你好运〜

另一个例子 。 在底部设置进度条,并根据滚动/加载和记录更改其可见性。 注意:您需要调用notifyDataSetChanged(); 向适配器添加/刷新数据的方法

  recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int total = linearLayoutManager.getItemCount(); int firstVisibleItemCount = linearLayoutManager.findFirstVisibleItemPosition(); int lastVisibleItemCount = linearLayoutManager.findLastVisibleItemPosition(); //to avoid multiple calls to loadMore() method //maintain a boolean value (isLoading). if loadMore() task started set to true and completes set to false if (!isLoading) { if (total > 0) if ((total - 1) == lastVisibleItemCount){ loadMore();//your HTTP stuff goes in this method loadingProgress.setVisibility(View.VISIBLE); }else loadingProgress.setVisibility(View.GONE); } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } }); 

实现load-more的想法是:

获取一个集合中的所有记录。 拿另一个将填充部分记录的集合,让我们说10条记录。 现在,当你到达底部时,填充集合中的下10条记录并通知列表。

所以你的代码将是这样的:

 ArrayList tempList; // which holds partial records tempList = getList(limit, 10); mAdapter = new RecyclerViewMaterialAdapter(new CardAdapter(getActivity(), tempList), 2); mRecyclerView.setAdapter(mAdapter); 

现在,代码加载下一条记录:

 limit += 10; tempList.addAll(getList(limit, 10)); mAdapter.notifyDataSetChanged(); 

为了显示他的加载器/进度,更好地使用load-more库

在onScroll方法中

 if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { // End has been reached Log.i("...", "end called"); // Do something new JSONAsyncTask().execute("http://walldroidhd.com/api.php"); loading = true; }