Как заставить recyclerview не переходить на вершину

#android #android-recyclerview

#Android #android-recyclerview

Вопрос:

Я выполняю getMessages() каждую минуту, и он каждый раз поднимается на вершину из-за

myadapter.notifyDataSetChanged();

Как я могу сделать так, чтобы Recyclerview сохранял свою позицию, даже если она обновлена или нет?

     private void getMessages() {
        StringRequest request = new StringRequest(Request.Method.POST, uRl, response -> {
            try{
                if (lstMessages != null) {
                    lstMessages.clear();
                }
                    JSONArray jsonArray = new JSONArray(response);
                    for (int i = 0; i < jsonArray.length(); i  ) {
                        try {
                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                            chatModel um = new chatModel();
                            um.setM_msg(jsonObject.getString("message"));
                            lstMessages.add(um);

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
            }catch (JSONException e2){
                e2.printStackTrace();
            }

            if (!started) {
                layoutManager = new LinearLayoutManager(this);
                layoutManager.setStackFromEnd(true);
                rv_msg.setLayoutManager(layoutManager);
                chat myadapter = new chat(this, lstMessages);
                rv_msg.setAdapter(myadapter);
                start();
            } else {
               chat myadapter = new chat(this, lstMessages);
                myadapter.notifyDataSetChanged();
            }
        }, error -> {
            MySingleton.getmInstance(this).MySingletonClear(this);
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                HashMap<String, String> param = new HashMap<>();
                param.put("aa", String.valueOf(aa));
                param.put("bb", String.valueOf(bb));

                return param;
            }
        };
        request.setRetryPolicy(new DefaultRetryPolicy(30000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        MySingleton.getmInstance(this).addToRequestQueue(request);
    }
  

Комментарии:

1. Проверьте Diff Util

Ответ №1:

Если вы очистите список данных и используете notifyDataSetChanges() recyclerview, все элементы будут обновлены.

Вы можете использовать отдельную функцию для предотвращения дублирования данных. Вот пример отдельной функции:

 private void distinctMessages(List<Message> newMessages) {
    if (lstMessages.size() < 1 || lstMessages == null) {
        lstMessages.addAll(newMessages);

        return;
    }

    for (Message newMessage: newMessages) {
        boolean hasSameMessages = false;
        
        for (Message currentMessage: lstMessages) {
            if (newMessage.getId().equals(currentMessage.getId())) {
                hasSameMessages = true;
                break;
            }
        }

        if (!hasSameMessages) {
            lstMessages.add(newMessage);
        }
    }
}
  

И вы можете использовать его в своем существующем коде следующим образом :

 private void getMessages() {
    StringRequest request = new StringRequest(Request.Method.POST, uRl, response -> {
        try{
            ArrayList<Message> newMessages = new ArrayList<Message>;
            JSONArray jsonArray = new JSONArray(response);

            for (int i = 0; i < jsonArray.length(); i  ) {
                try {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    chatModel um = new chatModel();
                    um.setM_msg(jsonObject.getString("message"));
                    newMessages.add(um);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            distinctMessages(newMessages);
        }catch (JSONException e2){
            e2.printStackTrace();
        }

        if (!started) {
            layoutManager = new LinearLayoutManager(this);
            layoutManager.setStackFromEnd(true);
            rv_msg.setLayoutManager(layoutManager);
            chat myadapter = new chat(this, lstMessages);
            rv_msg.setAdapter(myadapter);
            start();
        } else {
            chat myadapter = new chat(this, lstMessages);
            myadapter.notifyDataSetChanged();
        }
    }, error -> {
        MySingleton.getmInstance(this).MySingletonClear(this);
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            HashMap<String, String> param = new HashMap<>();
            param.put("aa", String.valueOf(aa));
            param.put("bb", String.valueOf(bb));

            return param;
        }
    };
    request.setRetryPolicy(new DefaultRetryPolicy(30000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    MySingleton.getmInstance(this).addToRequestQueue(request);
}
  

Пожалуйста, взгляните на документацию Android

Ответ №2:

Попробуйте добавить этот код

 View v = rv_msg.getChildAt(0);
int top = (v == null) ?0 : v.getTop();
layoutManager.scrollToPositionWithOffset(lstMessages.size(), top);
  

после myadapter.notifyDataSetChanged();

Ответ №3:

Вы пробовали notifyItemRangeChanged(int positionStart, int itemCount) ? Вы должны использовать это вместо notifyDataSetChanged() добавления новых элементов.

Добавьте метод внутри вашего адаптера, как показано ниже:

  public void appendListToAdapter(List<String> list) {
    int currentListSize = this.mList.size();
    this.mList.addAll(list);
    notifyItemRangeChanged(currentListSize, list.size());
}
  

Просто возьмите старый размер списка currentListSize и передайте его методу.

Теперь вызывайте этот метод, когда вам нужно добавить в свой список новые сообщения.