在保持滚动位置的同时更新 RecyclerView

Update RecyclerView while keeping its scroll position

如何在更新内容后将当前滚动位置保持在 RecyclerView 中?

onCreate我设置了一个任务重复如下:

private void setRepeatingAsyncTask() {

    final Handler handler = new Handler();
    Timer timer = new Timer();

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    try {
                        new getArrivals().execute(station_id);
                    } catch (Exception e) {
                        // error, do something
                    }
                }
            });
        }
    };
    timer.schedule(task, 0, 30000);  // interval of 30 seconds
}

AsyncTask会查询数据库获取最新列表内容:

private class getArrivals extends AsyncTask<Long, Void, Long>{

        @Override
        protected void onPreExecute(){
            //emptyMessage.setVisibility(VISIBLE);
            //recyclerView.setVisibility(GONE);
        }
        @Override
        protected Long doInBackground(Long... params) {
            long station_id = params[0];
            station = db.stationModel().getStationById(station_id);
            arrivals = db.arrivalModel().getNextArrivalsByStation(station_id, StaticClass.getDays());
            return station_id;
        }

        @Override
        protected void onPostExecute(Long result){
            if(getSupportActionBar() != null) {
                getSupportActionBar().setTitle(capitalize(station.name));
            }

            refreshList();
        }
}

完成任务后,我要求刷新列表:

private void refreshList(){

    arrivalListAdapter = new ArrivalListAdapter(getApplicationContext(), arrivals);
    staggeredGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(staggeredGridLayoutManager);
    recyclerView.setAdapter(arrivalListAdapter);
    Log.d("arrivals", arrivals.size()+"");
    arrivalListAdapter.notifyDataSetChanged();

    if(arrivals.size() == 0){
        emptyMessage.setVisibility(VISIBLE);
        recyclerView.setVisibility(GONE);

        new fetchArrivalsFromSource().execute(station.id);
    }else{
        emptyMessage.setVisibility(GONE);
        recyclerView.setVisibility(VISIBLE);
    }
}

我很确定我的问题的原因是我每次都在设置适配器。我试过在初始任务中设置它,但这导致列表根本没有更新。

您可以像这样获取当前位置、刷新适配器并平滑滚动到之前的位置:

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
  @Override protected int getVerticalSnapPreference() {
    return LinearSmoothScroller.SNAP_TO_START;
  }
};

然后设置要滚动到的位置:

smoothScroller.setTargetPosition(position);
layoutManager.startSmoothScroll(smoothScroller);