#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
и передайте его методу.
Теперь вызывайте этот метод, когда вам нужно добавить в свой список новые сообщения.