RecyclerView无尽的无限滚动问题

我试图用RecyclerView来实现无限的无限滚动,但是我只能得到前10条logging,没有得到下面的10条logging,甚至在底部滚动的时候没有得到任何进展。

而我想在滚动上得到下10条logging,等等…但只得到前10条logging

在这里我已经上传了我的JSON 副本 – 但我无法从相同的URL获取数据,这就是为什么我使用客户端的URL和本地主机。

我正在学习这个教程

这是我完整的代码,我可以知道我在哪里做错了?

JSON:

{ "names": [ { "name": "Name 1" }, { "name": "Name 2" }, .... { "name": "Name 60" } ] } 

日志:

 D/name -(13759): Name 1 D/name -(13759): Name 2 ....................... D/name -(13759): Name 60 

这里是我更新的代码,我正在使用它来parsingJSON数据

MainActivity.java:UPDATED

 public class MainActivity extends AppCompatActivity { private Toolbar toolbar; private TextView tvEmptyView; private RecyclerView mRecyclerView; private DataAdapter mAdapter; private LinearLayoutManager mLayoutManager; private ArrayList<Student> studentList; protected Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = (Toolbar) findViewById(R.id.toolbar); tvEmptyView = (TextView) findViewById(R.id.empty_view); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); studentList = new ArrayList<Student>(); handler = new Handler(); if (toolbar != null) { setSupportActionBar(toolbar); getSupportActionBar().setTitle("Android Students"); } loadData(); } // load initial data private void loadData() { new Parser().execute("http://10.0.2.2/jsons/mytest.txt"); } class Parser extends AsyncTask<String, Void, Boolean> { ProgressDialog dialog; @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(MainActivity.this); 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 = EntityUtils.toString(entity); JSONObject jsono = new JSONObject(data); JSONArray jarray = jsono.getJSONArray("names"); for (int i = 0; i < jarray.length(); i++) { JSONObject object = jarray.getJSONObject(i); Student actor = new Student(); actor.setName(object.getString("name")); Log.d("name - ", object.getString("name")); studentList.add(actor); } Log.d("MainActivity:StudentList ", "The size "+studentList.size()); return true; } //------------------>> } catch (ParseException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return false; } protected void onPostExecute(Boolean result) { dialog.cancel(); Log.d("MainActivity:StudentList ", "The size "+studentList.size()); ArrayList< Student > temArray = new ArrayList< Student >(studentList.subList(0, 10)); mAdapter = new DataAdapter(temArray, mRecyclerView); Log.d("MainActivity:TempList ", "The size "+temArray.size()); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); // 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(MainActivity.this); // use a linear layout manager mRecyclerView.setLayoutManager(mLayoutManager); if (studentList.isEmpty()) { mRecyclerView.setVisibility(View.GONE); tvEmptyView.setVisibility(View.VISIBLE); } else { mRecyclerView.setVisibility(View.VISIBLE); tvEmptyView.setVisibility(View.GONE); } mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore() { //add null , so the adapter will check view_type and show progress bar at bottom studentList.add(null); mAdapter.notifyItemInserted(studentList.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item studentList.remove(studentList.size() - 1); mAdapter.notifyItemRemoved(studentList.size()); //add items one by one int start = studentList.size(); int end = start + 10; for (int i = start + 1; i < end; i++) { mAdapter.notifyItemInserted(studentList.size()); } mAdapter.setLoaded(); //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); } }); } } } 

DataAdapter.java:

 public class DataAdapter extends RecyclerView.Adapter { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List<Student> studentList; // 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 DataAdapter(List<Student> students, RecyclerView recyclerView) { studentList = students; 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 studentList.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.list_row, parent, false); vh = new StudentViewHolder(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 StudentViewHolder) { Student singleStudent= (Student) studentList.get(position); ((StudentViewHolder) holder).tvName.setText(singleStudent.getName()); ((StudentViewHolder) holder).student= singleStudent; } else { ((ProgressViewHolder) holder).progressBar.setIndeterminate(true); } } public void setLoaded() { loading = false; } @Override public int getItemCount() { return studentList.size(); } public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) { this.onLoadMoreListener = onLoadMoreListener; } // public static class StudentViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public Student student; public StudentViewHolder(View v) { super(v); tvName = (TextView) v.findViewById(R.id.tvName); v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "OnClick :" + student.getName(), Toast.LENGTH_SHORT).show(); } }); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar) v.findViewById(R.id.progressBar1); } } } 

OnLoadMoreListener.java:

 public interface OnLoadMoreListener { void onLoadMore(); } 

Solutions Collecting From Web of "RecyclerView无尽的无限滚动问题"

一旦我使用这个代码解决它,我有同样的问题…首先..创build这个类

 public abstract class EndlessOnScrollListener extends OnScrollListener { public static String TAG = EndlessOnScrollListener.class.getSimpleName(); // use your LayoutManager instead private LinearLayoutManager llm; public EndlessOnScrollListener(LinearLayoutManager sglm) { this.lm = llm; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (!recyclerView.canScrollVertically(1)) { onScrolledToEnd(); } } public abstract void onScrolledToEnd(); } 

第二..在你的活动使用这个

 recyclerView.addOnScrollListener(new EndlessOnScrollListener() { @Override public void onScrolledToEnd() { if (!loading) { loading = true; // add 10 by 10 to tempList then notify changing in data } loading = false; } }); 

这对我有用….我希望它适合你。

尝试notifyItemRangeChanged

 yourCurrentList.addAll(newData); mAdapter.notifyItemRangeChanged(yourCurretList.size() + 1, newDataSize); 

我想这会帮助你。

1。

获得第一个11 recyclerview项目空白(并连续显示进度条),见下图截图:

loadData方法更改为:

 private void loadData() { new Parser().execute("http://clienturl.com/jsons/mytest.txt"); } 

2。

而我是想得到前10条logging,并滚动下10条logging等…

Parser onPostExecute方法更改为:

 protected void onPostExecute(Boolean result) { dialog.cancel(); ArrayList< Student > temArray = new ArrayList< Student >(studentList.subList(0, 10)); mAdapter = new DataAdapter(temArray, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); } 

并从onCreate方法中删除以下行:

  mAdapter = new DataAdapter(studentList, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); 

尝试改变

 int i = start + 1; i <= end; i++ 

在for循环中

 int i = start + 1; i < end; i++ 

<=validation会添加一个额外的项目。

问题1 :在设置用于RecyclerView的LayoutManager之前,您已经创build了一个新的mAdapter实例。 因此, DataAdapter中添加ScrollListener的构造函数代码不会被执行,因为recyclerView.getLayoutManager()返回null

  if (recyclerView.getLayoutManager() instanceof LinearLayoutManager){ // code to add ScrollListener is never executed } 

修复 :首先为Recyclerview设置LayoutManager ,然后像下面那样创build适配器:

  // use a linear layout manager mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new DataAdapter(temArray, mRecyclerView); // set the adapter object to the Recyclerview mRecyclerView.setAdapter(mAdapter); 

问题2:您已经使用temArray创buildDataAdapter但是在onLoadMore()您使用studentList来添加/删除新项目,因为studentList没有绑定到mAdapter您的更改不会反映在UI中。

修复:将 temArray声明为类级variables,并使用temArray来操作这些项。

  //class variable private ArrayList<Student> temArray = new ArrayList<Student>(); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item temArray.remove(temArray.size() - 1); mAdapter.notifyItemRemoved(temArray.size()); //add items one by one int start = temArray.size(); int end = start + 10; if(end<=studentList.size()){ temArray.addAll(studentList.subList(start,end)); } mAdapter.setLoaded(); } }, 2000); 

更换

 private List<Student> studentList; 

 private List<Object> list; 

也取代

 @Override public int getItemViewType(int position) { return studentList.get(position) != null ? VIEW_ITEM : VIEW_PROG; } 

 @Override public int getItemViewType(int position) { return list.get(position) instanceof Student ? VIEW_ITEM : VIEW_PROG; } 

为List的检测结束您可以使用

 @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); // When went to the end of the list, load more posts if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (linearLayoutManager.findLastVisibleItemPosition() >= linearLayoutManager.getItemCount() - 1) { // Grow List } } } 

也用于添加加载项目。 在适配器中添加此代码

 public void addLoadingView(){ list.add(new Object()); notifyDataSetChanged(); } 
 for (int i = start + 1; i < end; i++) { studentList.add(add data here) ; mAdapter.notifyItemInserted(studentList.size()); } 
  mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() { @Override public void onLoadMore() { //add null , so the adapter will check view_type and show progress bar at bottom studentList.add(null); mAdapter.notifyItemInserted(studentList.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { // remove progress item studentList.remove(studentList.size() - 1); mAdapter.notifyItemRemoved(studentList.size()); //add items one by one int start = studentList.size(); int end = start + 10; for (int i = start + 1; i < end; i++) { // studentList.add(); mAdapter.notifyItemInserted(studentList.size()); } mAdapter.setLoaded(); //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); } }); 

好的,所以你插入了进度条,然后你已经删除它,但你从来没有插入下一个学生显示…像studentList.add();

我希望能解决你的问题…祝你好运