У меня сложная проблема, и у меня тоже проблемы с ее объяснением, поэтому наберитесь терпения, пожалуйста
У меня есть бесконечная прокрутка RecyclerView
(только сверху вниз).
В этом RecyclerView
отображаются сообщения, полученные телефоном от первого до последнего, а при достижении последнего из них снова отображается первое (с прокруткой только вниз) и т. Д.
Я реализовал это решение с помощью функции автопрокрутки, которая всегда увеличивает мою позицию, чтобы плавно переходить к следующей. В адаптере я получаю фактическую позицию элемента в списке и связываю ее с моим видоискателем (то есть: если у меня есть 2 элемента, и позиция, которую нужно показать, является 5-й, я получу 1-й элемент с логикой показывать пункт таким образом: 1-2-1-2-1).
Моя проблема в том, что все работает нормально, но когда новые элементы добавляются в источник данных во время прокрутки, и я вызываю NotifyDataSetChangd
, все обновляется, и мой список мигает, изменяя текущие отображаемые элементы.
Я пытаюсь объяснить проблему на примере: предположим, мой текущий видимый индекс - 5-й в моей бесконечной прокрутке, а мой источник содержит 2 элемента.
Как вы можете видеть в столбце «до», при видимом индексе 5 я увижу элемент B.
Теперь приходит сообщение, и источник уведомляется об изменении, обновляя все.
позиция - до - после
0 A A
1 B B
2 A C
3 B A
4 A B
5 B C
6 A A
7 B B
8 A C
9 B A
Что теперь происходит: список мигает, и отображается элемент C (индекс 5 после столбца).
Что я хочу: список должен продолжаться в том же виде, в каком он есть сейчас, и после фактического вращения A-B он показывает вновь добавленные элементы C, не мигая и не обновляя все.
Это адаптер (более или менее он выполняет всю работу, я думаю, что это единственный значимый код)
import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import utilitapps.com.ememories.R;
import utilitapps.com.ememories.db_objects.SMSMessage;
public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MessagesViewHolder> {
private ArrayList<SMSMessage> SMSMessages;
private int textSize;
private Typeface custom_font;
private int lastShownPosition;
LinkedHashMap<Integer, Integer> offsets;
Integer lastEntryKey;
public MessagesAdapter(int textSize, Typeface custom_font, ArrayList<SMSMessage> SMSMessages) {
this.SMSMessages = SMSMessages;
this.textSize = textSize;
this.custom_font = custom_font;
this.lastShownPosition = 0;
this.offsets = new LinkedHashMap<>();
offsets.put(0, -1);
}
public void addItem(SMSMessage msg) {
SMSMessages.add(msg);
if (SMSMessages.size() > 1) {
offsets.remove(lastEntryKey);
offsets.put(lastEntryKey, lastShownPosition);
//aggiungo poi l'ultima
lastEntryKey = lastShownPosition + 1;
offsets.put(lastEntryKey, -1);
} else {
}
notifyDataSetChanged();
}
public int getActualItemCount() {
if (SMSMessages == null) {
SMSMessages = new ArrayList<>();
}
return SMSMessages.size();
}
@Override
public int getItemCount() {
return Integer.MAX_VALUE;
}
@NonNull
@Override
public MessagesAdapter.MessagesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MessagesAdapter.MessagesViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_message, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MessagesAdapter.MessagesViewHolder holder, int position) {
lastShownPosition = position;
holder.bind(getSMSMessage(position));
}
private SMSMessage getSMSMessage(int position) {
if (SMSMessages.size() == 0) {
return null;
}
int itemLastIndex = 1;
for (Map.Entry<Integer, Integer> entry :
offsets.entrySet()) {
if (entry.getValue() == -1) {
return SMSMessages.get(position % SMSMessages.size());
}
if (position >= entry.getKey() && position <= entry.getValue()) {
return SMSMessages.subList(0, itemLastIndex).get(position % SMSMessages.subList(0, itemLastIndex).size());
}
itemLastIndex++;
}
return null;
}
class MessagesViewHolder extends RecyclerView.ViewHolder {
TextView tvMsgText;
MessagesViewHolder(View itemView) {
super(itemView);
tvMsgText = itemView.findViewById(R.id.tvMsgText);
tvMsgText.setTextSize(textSize);
tvMsgText.setTypeface(custom_font);
}
void bind(SMSMessage SMSMessage) {
if (SMSMessage != null && SMSMessage.isValid()) {
try {
tvMsgText.setText(SMSMessage.getMessageText());
} catch (Exception ignored) {
tvMsgText.setText("");
}
} else {
tvMsgText.setText("");
}
}
}
}
как вы можете видеть, я пытался реализовать решение, хранящее карту индексов, чтобы я мог заполнить свой список этим примером (следуя этой логике: ABAB (элемент добавлен, но A уже загружен) ABCAB C ...), но это не так работает, и я не совсем понимаю, почему.
Я пытался уточнить, если не спросить свободно
спасибо за помощь
Я также открыт для новых подходов, это тот, который я использовал, но это может быть неправильно, я действительно не знаю