Adapter of RecyclerView doesn't update data after changing the array

Viewed 192

I have an abstract class "ListItem" with two subclasses - "Header"(Data) and "Event". Depending on the situation, the array should be displayed either as "Header" - "Events of this data", or just events. The created object of the "Event" class is passed to the main fragment from a separate activity. If I only need to display events, I just write it to an array and update the adapter data, it works. If, after creating a class object, I need to display it and existing events in the form "Header" - "Events", then the adapter for some reason is not updated and the new event is not displayed. If you close the application and reopen it, the event appears in its normal form with a header.

Here's my RV Adapter

public class EventAdapter extends RecyclerView.Adapter<EventAdapter.EventViewHolder> {
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
private static final String TAG = "myLogs";

private ArrayList<ListItem> list;


final SparseBooleanArray selectedItems = new SparseBooleanArray();
private int currentSelectedPos;

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM", myDateFormatSymbols);

public EventAdapter(ArrayList<ListItem> items){
    list = items;
}


public ArrayList<ListItem> getItems(){
    return list;
}

private EventAdapterListener itemClickListener;

public interface EventAdapterListener {
    void onItemClick(int position);
    void onItemLongClick(int position);
}

public void setListener(EventAdapterListener listener){
        itemClickListener = listener;
}


private OnItemCheckedListener OnItemChecked;
public interface OnItemCheckedListener {
    void onItemChecked(int position, boolean isImportant);
}

public void setOnItemCheckedListener (OnItemCheckedListener listener){
    OnItemChecked = listener;
}


public static class EventViewHolder extends RecyclerView.ViewHolder{
   public TextView TVtitle;
   public TextView TVcomment;
   public CheckBox CBimportance;
   public TextView TVdate;


   //public EventViewHolder(@NonNull View itemView, final EventAdapterListener listener) {
   public EventViewHolder(@NonNull View itemView) {
       super(itemView);
   }
}

public void removeAllObjectsOf(Class<? extends ListItem> cls) {
    Iterator itr = list.iterator();
    while (itr.hasNext()) {
        if (itr.next().getClass().equals(cls)) {
            itr.remove();
        }
    }
    notifyDataSetChanged();
}

Comparator<ListItem> dateComparator = new Comparator<ListItem>() {
    @Override
    public int compare(ListItem event, ListItem t1) {
        return ((Event)(event)).Date.compareTo(((Event)t1).Date);
    }
};

Comparator<ListItem> importanceComparator = new Comparator<ListItem>() {
    @Override
    public int compare(ListItem event, ListItem t1) {
        return ((Event)(event)).IsImportant.compareTo(((Event)t1).IsImportant);
    }
};

Comparator<ListItem> nameComparator = new Comparator<ListItem>() {
    @Override
    public int compare(ListItem event, ListItem t1) {
        return ((Event)(event)).Name.compareTo(((Event)t1).Name);
    }
};

Comparator<ListItem> completenessComparator = new Comparator<ListItem>() {
    @Override
    public int compare(ListItem event, ListItem t1) {
        return ((Event)(event)).IsComplete.compareTo(((Event)t1).IsComplete);
    }
};

public void sortBy(Comparator<ListItem> comparator, ArrayList<ListItem> list) {
    removeAllObjectsOf(Header.class);
    Collections.sort(list, comparator);
}


public void groupByDate()
{

    ArrayList<ListItem> result = new ArrayList<>();

    removeAllObjectsOf(Header.class);
    sortBy(dateComparator, list);
    ArrayList<Long> dates = new ArrayList<>();
    for (ListItem event: list)
    {
        if (!(dates.contains(((Event)event).getDate())))
        {
            dates.add(((Event)event).getDate());
            ArrayList<ListItem> ei = getItemsbyDate(list, ((Event)event).getDate());
            Header header = new Header();
            header.setHeader(String.valueOf(((Event)event).getDate()));
            result.add(header);
            result.addAll(ei);
        }
    }

    list = result;
    notifyDataSetChanged();
}

public ArrayList<ListItem> getItemsbyDate(ArrayList<ListItem> items, Long date){
    ArrayList<ListItem> result = new ArrayList<>();

    for (ListItem ci : items){
        if (((Event)ci).getDate().equals(date)){
            result.add(ci);
        }
    }

    return result;
}

public void removeItem(int position) {
    list.remove(position);
    notifyItemRemoved(position);
    notifyItemRangeChanged(position,list.size());
}

@Override
public int getItemViewType(int position) {
    if (isPositionHeader(position))
        return TYPE_HEADER;
    return TYPE_ITEM;
}

private boolean isPositionHeader(int position) {
    return list.get(position) instanceof Header;
}

private static DateFormatSymbols myDateFormatSymbols = new DateFormatSymbols(){

    @Override
    public String[] getMonths() {
        return new String[]{"января", "февраля", "марта", "апреля", "мая", "июня",
                "июля", "августа", "сентября", "октября", "ноября", "декабря"};
    }

};


@NonNull
@Override
public EventViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    if (viewType == TYPE_HEADER){
        View v = inflater.inflate(R.layout.group_layout, parent, false);
        return new VHHeader(v);
    } else {
        View v = inflater.inflate(R.layout.list_item_cardview, parent, false);
        return new VHItem(v);
    }
}

@Override
public void onBindViewHolder(@NonNull EventViewHolder holder, final int position)
{
    if (holder instanceof VHHeader){
        Header currentItem = (Header) list.get(position);
        VHHeader VHheader = (VHHeader) holder;
        VHheader.txtTitle.setText(simpleDateFormat.format(Long.parseLong(currentItem.getHeader())));
    } else if (holder instanceof VHItem) {
        final Event event = (Event) list.get(position);
        VHItem VHitem = (VHItem) holder;
        VHitem.txtName.setText(event.getName());
        VHitem.txtDate.setText(simpleDateFormat.format(event.getDate()));
        VHitem.TVcomment.setText(event.getComment());

        VHitem.CBimportance.setOnCheckedChangeListener(null);

        VHitem.CBimportance.setChecked(event.getImportant());

        VHitem.CBimportance.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                event.IsImportant = b;
                OnItemChecked.onItemChecked(position, b);
            }
        });


        VHitem.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (selectedItems.size() > 0 && itemClickListener != null){
                    itemClickListener.onItemClick(position);
                }
            }
        });

        VHitem.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                if (itemClickListener != null){
                    itemClickListener.onItemLongClick(position);
                }
                return true;
            }
        });

        if (currentSelectedPos == position) currentSelectedPos = -1;
    }
}

@Override
public int getItemCount() {
    return (list == null) ? 0 : list.size();
}

void deleteEvents(){
    List<ListItem> selectedEvents = new ArrayList<>();
    for (ListItem item : list){
        if (item instanceof Event){
            if (((Event) item).getSelected()){
                selectedEvents.add(item);
            }
        }

    }

    list.removeAll(selectedEvents);

    //notifyDataSetChanged();
    currentSelectedPos = -1;

    deleteEmptyHeaders();

}


public int getCountofHeaderItems(Header header)
{
    int k = 0;
    for (ListItem item: list)
    {
        if (item instanceof Event){
            if (((Event) item).Date.equals(Long.parseLong(header.getHeader()))){
                k++;
            }
        }
    }
    return k;
}

void deleteEmptyHeaders(){
    List<Header> headers = new ArrayList<>();
    for (ListItem event : list){
        if (event instanceof Header){
            if (getCountofHeaderItems((Header)event) == 0){
                headers.add((Header)event);
            }
        }
    }
    list.removeAll(headers);
}

void toggleSelection(int position) {
    if (getItemViewType(position) == TYPE_ITEM){
        currentSelectedPos = position;
        if (selectedItems.get(position)) {
            selectedItems.delete(position);
            ((Event)list.get(position)).setSelected(false);
        } else {
            selectedItems.put(position, true);
            ((Event)list.get(position)).setSelected(true);
        }
        notifyItemChanged(position);
    }

}


class VHHeader extends EventAdapter.EventViewHolder {
    TextView txtTitle;

    public VHHeader(View itemView) {
        super(itemView);
        this.txtTitle = (TextView) itemView.findViewById(R.id.tvTitleGroup);
    }
}

class VHItem extends EventAdapter.EventViewHolder {
    TextView txtName;
    TextView txtDate;
    TextView TVcomment;
    CheckBox CBimportance;
    public VHItem(View itemView) {
        super(itemView);
        this.txtName = (TextView) itemView.findViewById(R.id.tvTitle);
        this.txtDate = (TextView) itemView.findViewById(R.id.tvDate);
        this.TVcomment = (TextView) itemView.findViewById(R.id.tvComment);
        this.CBimportance = (CheckBox) itemView.findViewById(R.id.cbIconImportant);
    }
}

}

Here's my MainFragment:

private final static String ONLY_EVENTS = "ONLY_EVENTS";
private final static String GROUP_EVENTS_BY_DATE = "GROUP_EVENTS_BY_DATE";
ArrayList<ListItem> events;
private String ShowMode = ONLY_EVENTS;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_first_new, container, false);

    events = read(this.getActivity(), PROCESSED_EVENTS);
    if (events == null)
        events = new ArrayList<ListItem>();



    rvEvent = view.findViewById(R.id.recyclerview);
    rvEvent.setHasFixedSize(true);
    lmEvent = new LinearLayoutManager(this.getContext());
    adapterEvent = new EventAdapter(events);

    rvEvent.setLayoutManager(lmEvent);

    rvEvent.setAdapter(adapterEvent);

    ShowEvents(ShowMode);
    initSwipe();
    

 

    return view;
}

public void ShowEvents(String mode){
    switch (mode){
        case ONLY_EVENTS:
            adapterEvent.removeAllObjectsOf(Header.class);
            break;
        case GROUP_EVENTS_BY_DATE:
             adapterEvent.groupByDate();
            break;

    }
}
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == Activity.RESULT_OK && requestCode == 1) {
        Event nd = (Event) data.getSerializableExtra("class");

        events.add(nd);

        write(this.getActivity(), events, PROCESSED_EVENTS);

        if (ShowMode.equals(GROUP_EVENTS_BY_DATE))
            adapterEvent.groupByDate();

        adapterEvent.notifyDataSetChanged();
    }
}


public static void write(Context context, ArrayList<ListItem> events, String Key) {
    Gson gson = new Gson();
    String jsonString = gson.toJson(events);
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = pref.edit();

    editor.putString(Key, jsonString);
    editor.apply();
}

public static ArrayList<ListItem> read(Context context, String Key) {
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
    String jsonString = pref.getString(Key, "");

    Gson gson = new Gson();
    Type type = new TypeToken<ArrayList<Event>>() {
    }.getType();
    ArrayList<ListItem> list = gson.fromJson(jsonString, type);
    return list;
}

This is how the Event is sent from the activity:

Intent intent = new Intent(NewEvent.this, FirstFragment.class);
                    //intent.putExtra("name", (String) etName.getText().toString());
                    objectEvent = new Event(etName.getText().toString(), date, etComment.getText().toString(), etType.getText().toString(), etNotif.getText().toString(), swIsComplete.isChecked(), false);
                    intent.putExtra("class", objectEvent);
                    setResult(RESULT_OK, intent);
                    finish();

UPD. In OnActivityResult after executing the line adapterEvent.groupByDate(); nothing changes. Changes take place in the array list in the adapter, but for some reason they do not go into the array that is used in the fragment. In the ShowEvents procedure, the same line of code works, and after it the array is changed.

0 Answers
Related