ListView设置setOnScrollListener加载分页数据后返回顶部如何解决
问题解决方法
问题根源
你每次分页加载完新数据后,都重新创建SimpleAdapter实例并重新给ListView绑定适配器,这会让ListView判定为全新数据源,直接重置滚动位置回到顶部,是问题的核心原因。
另外你当前代码还有两个隐含问题:
- 滚动监听没有加加载状态判断,滚动到底部时会重复触发多次加载请求
- 在子线程(doInBackground)中操作UI控件
pDialog.dismiss(),会抛出异常导致崩溃
修复步骤
- 初始化阶段一次性设置适配器,不要每次加载都重建
在Activity的onCreate方法中完成适配器初始化和绑定:
// 全局变量声明 private boolean isLoading = false; // 新增加载状态标记,防止重复加载 // onCreate里的逻辑 polist = new ArrayList<>(); listAdapter = new SimpleAdapter(PoActivity.this, polist, R.layout.po_row, new String[]{"emp", "status"}, new int[]{R.id.name, R.id.status}); listView.setAdapter(listAdapter);
- 修改滚动监听,新增加载状态判断
listView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // 新增isLoading判断,避免同一时间触发多个加载请求 if (!isLoading && firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0){ nextpage = nextpage + 1; new getJSON().execute(); } } });
- 改造AsyncTask逻辑,删除重建适配器的代码,仅更新数据源后通知适配器刷新即可
private class getJSON extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); isLoading = true; // 开始加载,标记状态为加载中 footer.setVisibility(View.VISIBLE); pDialog = new ProgressDialog(PoActivity.this); pDialog.setMessage("Please Wait..."); pDialog.setCancelable(false); pDialog.show(); } @Override protected Void doInBackground(Void... voids) { Handler handler = new Handler(); String po = handler.makeServiceCall(url + "?page=" + nextpage); if (po != null){ try { JSONObject obj = new JSONObject(po); JSONArray objArray = obj.getJSONArray("data"); for (int i = 0; i < objArray.length(); i++){ JSONObject data = objArray.getJSONObject(i); String employee = data.getString("name"); String status = data.getString("status"); HashMap<String, String> datarow = new HashMap<>(); datarow.put("emp", employee); datarow.put("status", status); polist.add(datarow); } }catch (final JSONException e){ Log.e(TAG, "Json parsing error: " + e.getMessage()); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "Json parsing error: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } }); } }else { Log.e(TAG,"Couldn't get json from server"); endpage = 0; runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "Couldn't get json from server. check logcat", Toast.LENGTH_SHORT).show(); } }); } // 删除这里的pDialog.dismiss(),子线程不允许操作UI控件 return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); pDialog.dismiss(); footer.setVisibility(View.GONE); isLoading = false; // 加载完成,标记状态为非加载中 // 删除原有重新创建适配器、重新setAdapter的代码,仅保留下面这行通知刷新即可 listAdapter.notifyDataSetChanged(); } }
修改后加载新数据时只会在原有列表末尾追加内容,不会重置滚动位置,也不会出现重复加载、子线程操作UI的异常问题。
内容的提问来源于stack exchange,提问作者PieceofShid
相关产品推荐
相关产品推荐

