Witam mam taki problem, że mam zagęszczone listy - przedstawię to w formie schematu Fragment > RecyclerView > ListItem (który ma w sobie właśnie layout itemu i kolejny RecyclerView) i tak jest to zagęszczone i tak, wszystko fajnie działa oprócz jednej rzeczy. Adapter dostaje dane z database, i nie ma jak sprawdzić czy jest item inserted czy deleted czy moved więc dawałem notifyDataSetChanged()
, ale zauważyłem teraz, że gdy itemów jest więcej niż ekran i trzeba przewijać w dół to gdy się cokolwiek doda i tak cofa do góry na sam początek a wszystko co było zwinięte lub rozwinięte rozwija się od nowa. Wyczytałem że VIewHoldery tworzą się wtedy od nowa.
Tak więc chciałem początkowo użyć Callbacku z diffUtil ale nowe adaptery tworzę dynamicznie, nie przechowuje instancji więc nic mi to nie dało... Nie wiem może ktoś ma pomysł jakby to zrobić?
Niżej troszkę kodu, całość na https://github.com/Xezolpl/My-Library
To jest adapter od notatek, notatki siedzą w chapter'ach dlatego ViewHolder jest ChapterNoteViewHolder - dla tych i dla tych gdyż różnią się minimalnie (chapters mają 2 recViewy - jeden na notki jeden na cytaty)
public class NotesRecViewAdapter extends RecyclerView.Adapter<ChaptersNotesViewHolder> {
private List<Note> notes = new ArrayList<>();
private List<ChaptersNotesViewHolder> viewHolders = new ArrayList<>();
private Context context;
private LayoutInflater inflater;
NotesRecViewAdapter(Context context) {
this.context = context;
this.inflater = LayoutInflater.from(context);
}
void setNotesList(List<Note> notes) {
final NoteDiffCallback callback = new NoteDiffCallback(this.notes, notes);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);
this.notes.clear();
this.notes.addAll(notes);
diffResult.dispatchUpdatesTo(this);
}
List<ChaptersNotesViewHolder> getViewHolders() {
return viewHolders;
}
@NonNull
@Override
public ChaptersNotesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = inflater.inflate(R.layout.listitem_note, parent, false);
ChaptersNotesViewHolder viewHolder = new ChaptersNotesViewHolder(v, context, ChaptersNotesViewHolder.FROM_NOTE);
viewHolders.add(viewHolder);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ChaptersNotesViewHolder holder, int position) {
holder.setData(notes.get(position), position);
}
@Override
public int getItemCount() {
return notes.size();
}
}
ChaptersNotesViewHolder(@NonNull View itemView, Context context, int parent) {
super(itemView);
this.context = context;
this.parent = parent;
activity = (FragmentActivity) context;
initWidgets();
setOnClickListeners();
if (parent == FROM_CHAPTER) {
quotesAdapter = new QuotesRecViewAdapter(context);
quotesRecView.setLayoutManager(new GridLayoutManager(context, 1));
}
adapter = new NotesRecViewAdapter(context);
}
private void initWidgets() {
textView = itemView.findViewById(R.id.textView);
recView = itemView.findViewById(R.id.recView);
wholeRelLay = itemView.findViewById(R.id.wholeRelLay);
if (parent == FROM_NOTE) {
marker_imgView = itemView.findViewById(R.id.marker_imgView);
} else {
quotesRecView = itemView.findViewById(R.id.quotes_recView);
quotesRecView.setVisibility(View.GONE);
}
moreBtn = itemView.findViewById(R.id.moreBtn);
setRecViewVisible(true);
}
private void setOnClickListeners() {
wholeRelLay.setOnClickListener(view -> {
if (isRecViewVisible) {
setRecViewVisible(false);
if (parent == FROM_CHAPTER) setQuotesViewVisible(false);
} else {
setRecViewVisible(true);
if (parent == FROM_CHAPTER) setQuotesViewVisible(true);
}
});
wholeRelLay.setOnLongClickListener(view -> {
expandWithChildren(!isRecViewVisibleWithChildren);
return true;
});
moreBtn.setOnClickListener(view -> {
PopupMenu popupMenu = new PopupMenu(context, view);
popupMenu.inflate(R.menu.chapter_note_popup_menu);
if (parent == FROM_NOTE) {
popupMenu.getMenu().getItem(2).setVisible(false);
}else{
popupMenu.getMenu().getItem(1).setTitle("Edit chapter");
popupMenu.getMenu().getItem(3).setTitle("Delete chapter");
}
popupMenu.setOnMenuItemClickListener(menuItem -> {
switch (menuItem.getItemId()) {
case R.id.addMenuBtn: {
Intent intent = new Intent(context, AddNoteActivity.class);
if (parent == FROM_CHAPTER) {
intent.putExtra("chapter", parentChapter);
intent.putExtra("parent", FROM_CHAPTER);
setQuotesViewVisible(true);
} else {
intent.putExtra("note", parentNote);
intent.putExtra("parent", FROM_NOTE);
}
context.startActivity(intent);
setRecViewVisible(true);
break;
}
case R.id.editMenuBtn: {
Intent intent;
if (parent == FROM_CHAPTER) {
intent = new Intent(context, AddChapterActivity.class);
intent.putExtra("chapter", parentChapter);
} else {
intent = new Intent(context, AddNoteActivity.class);
intent.putExtra("note", parentNote);
intent.putExtra("parent", EDITION);
}
context.startActivity(intent);
break;
}
case R.id.insertQuoteMenuBtn: {
Intent intent = new Intent(context, InsertQuoteActivity.class);
intent.putExtra("chapter", parentChapter);
setRecViewVisible(true);
setQuotesViewVisible(true);
context.startActivity(intent);
break;
}
case R.id.deleteMenuBtn: {
DeletingManager deletingManager = new DeletingManager((AppCompatActivity) context);
if (parent == FROM_CHAPTER) {
deletingManager.showDeletingDialog(context.getString(R.string.del_chapter),
context.getString(R.string.delete_chapter),
DeletingManager.CHAPTER,
parentChapter);
} else {
deletingManager.showDeletingDialog(context.getString(R.string.del_note),
context.getString(R.string.delete_note),
DeletingManager.NOTE,
parentNote);
}
break;
}
default:
return false;
}
return true;
});
MenuPopupHelper menuHelper = new MenuPopupHelper(context, (MenuBuilder) popupMenu.getMenu(), view);
menuHelper.setForceShowIcon(true);
menuHelper.show();
});
}
void setData(Chapter chapter) {
parentChapter = chapter;
textView.setText(chapter.getName());
NoteViewModel noteModel = ViewModelProviders.of(activity).get(NoteViewModel.class);
noteModel.getNotesByParent(chapter.getId()).observe(activity, notes -> {
adapter = new NotesRecViewAdapter(context);
adapter.setNotesList(notes);
recView.setAdapter(adapter);
recView.setLayoutManager(new GridLayoutManager(context, 1));
QuoteViewModel quoteViewModel = ViewModelProviders.of(activity).get(QuoteViewModel.class);
quoteViewModel.getQuotesByChapter(parentChapter.getId()).observe(activity, quotes -> {
quotesAdapter.setQuotes(quotes);
quotesRecView.setAdapter(quotesAdapter);
});
}
);
}
void setData(Note note, int position) {
parentNote = note;
textView.setText(note.getNote());
try {
Drawable drawable;
int markerType = note.getMarkerType();
if (markerType == Markers.NUMBER_MARKER || markerType == Markers.LETTER_MARKER) {
drawable = Markers.getLetterMarker(markerType, position, note.getColor());
} else {
drawable = Markers.getSimpleMarker(context, note.getMarkerType(), note.getColor());
}
marker_imgView.setImageDrawable(drawable);
} catch (IOException e) {
e.printStackTrace();
}
NoteViewModel noteModel = ViewModelProviders.of(activity).get(NoteViewModel.class);
noteModel.getNotesByParent(note.getId()).observe(activity, notes -> {
adapter.setNotesList(notes);
recView.setAdapter(adapter);
recView.setLayoutManager(new GridLayoutManager(context, 1));
});
}
private void setRecViewVisible(boolean b) {
if (b) {
recView.setVisibility(View.VISIBLE);
isRecViewVisible = true;
} else {
recView.setVisibility(View.GONE);
isRecViewVisible = false;
}
}
private void setQuotesViewVisible(boolean b) {
quotesRecView.setVisibility(b ? View.VISIBLE : View.GONE);
}
public void expandWithChildren(boolean b) {
for (ChaptersNotesViewHolder viewHolder : adapter.getViewHolders()) {
viewHolder.expandWithChildren(b);
}
setRecViewVisible(b);
isRecViewVisibleWithChildren = b;
}
}
No i sam callback
public class NoteDiffCallback extends DiffUtil.Callback {
private List<Note> newNotes;
private List<Note> oldNotes;
public NoteDiffCallback(List<Note> newNotes, List<Note> oldNotes) {
this.newNotes = newNotes;
this.oldNotes = oldNotes;
}
@Override
public int getOldListSize() {
return oldNotes.size();
}
@Override
public int getNewListSize() {
return newNotes.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldNotes.get(oldItemPosition).getId().equals(newNotes.get(newItemPosition).getId());
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Note oldN = oldNotes.get(oldItemPosition);
Note newN = newNotes.get(newItemPosition);
return oldN.getMarkerType() == newN.getMarkerType() &&
oldN.getColor() == newN.getColor() &&
oldN.getNote().equals(newN.getNote());
}
}