I have a WhatsApp chat, as in my application, and they recently added new functionality that groups images in albums if they are sent in a sequence of four or more images and there are no messages between them. As in the picture below:

So, I implemented my RecyclerView adapter, which displays all the contents separately, which means that this message, image, sound, etc., each of them will be on a separate line in my adapter. Therefore, I would like to do what WhatsApp has completed and is implementing this grouping of images into albums, if there are more than 4 of them sent in a row. How can I achieve this?
getItemViewType() , . , .
PS: Feed - , , , , .. mItems - .
:
public class FeedAdapter extends BaseSkeletonAdapter<Feed> implements FeedHolder.FeedHolderListener{
  private static final int HOLDER_COMMENT = 1;
  private static final int HOLDER_IMAGE = 2;
  private static final int HOLDER_FILE = 3;
  private static final int HOLDER_AUDIO = 4;
  private static final int HOLDER_MARKER = 5;
  private static final int HOLDER_EMPTY = 6;
  private final FeedItemListener mListener;
  private final int mAvatarSize;
  private final String mUserId;
  private final int mPictureSize;
  private final int mSkeletonColor;
  public FeedAdapter(FeedItemListener listener, String userId, int avatarSize, int pictureSize, int skeletonColor) {
    super(2);
    mListener = listener;
    mUserId = userId;
    mAvatarSize = avatarSize;
    mPictureSize = pictureSize;
    mSkeletonColor = skeletonColor;
  }
  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    switch (viewType){
      case HOLDER_COMMENT:
      case HOLDER_IMAGE:
        System.out.println("It is an image!");
      case HOLDER_FILE:
      case HOLDER_MARKER:
      case HOLDER_AUDIO:
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_feed, parent, false);
        return new FeedHolder(view, this, mPictureSize);
      case HOLDER_EMPTY:
      default:
        View empty = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_empty, parent, false);
        return new EmptyPlaceholderViewHolder(empty, R.string.placeholder_feed_empty_title, R.string.placeholder_feed_empty_description, R.drawable.ic_feed_placeholder);
    }
  }
  @Override
  protected void onBind(RecyclerView.ViewHolder holder, int position) {
    if(!(holder instanceof EmptyPlaceholderViewHolder)){
      Feed feed = mItems.get(position);
      
      
      
      if (holder instanceof FeedHolder) {
        if (mUserId.equals(feed.getCreatedById())) {
          ((FeedHolder) holder).onBind(feed, mUserId, mAvatarSize);
        }else {
          ((FeedHolder) holder).onBind(feed, mUserId, mAvatarSize);
        }
      }
    }
  }
  @Override
  protected void onBind(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {
    if (payloads.isEmpty()) {
      onBindViewHolder(holder, position);
    }else {
      if (holder instanceof FeedHolder) {
        ((FeedHolder) holder).onBind(mItems.get(position), payloads, mUserId, mAvatarSize);
      }
    }
  }
  @Override
  protected void setHolderSkeleton(RecyclerView.ViewHolder holder) {
    if (holder instanceof FeedHolder) {
      ((FeedHolder) holder).setHolderSkeleton(R.drawable.rounded_skeleton, mSkeletonColor);
    }
  }
  @Override
  protected void clearHolderSkeleton(RecyclerView.ViewHolder holder) {
    if (holder instanceof FeedHolder) {
      ((FeedHolder) holder).clearHolderSkeleton();
    }
  }
  @Override
  public int getItemViewType(int position) {
    if(mSkeletonMode){
      return HOLDER_COMMENT;
    } if (mItems != null && mItems.size() > 0 && position >= 0 && position < mItems.size()) {
      Feed feed = mItems.get(position);
      if (feed != null) {
        String type = feed.getFeedType();
        if (type != null) {
          switch (type) {
            case FEED_IMAGE:
              return HOLDER_IMAGE;
            case FEED_AUDIO:
              return HOLDER_AUDIO;
            case FEED_FILE:
              return HOLDER_FILE;
            case FEED_MARKER:
              return HOLDER_MARKER;
            case FEED_COMMENT:
            default:
              return HOLDER_COMMENT;
          }
        }
      }
      return HOLDER_COMMENT;
    }else {
      return HOLDER_EMPTY;
    }
  }
  public List<Feed> getItems() {
    return mItems;
  }
  public void swap(List<Feed> feedList) {
    if (mItems == null) {
      mItems = new ArrayList<>();
    }
    mItems.clear();
    mItems.addAll(feedList);
  }
  @Override
  public void toggleLike(final int pos){
    if(mListener != null && pos >= 0 && pos < mItems.size()){
      mListener.toggleLike(mItems.get(pos));
    }
  }
  @Override
  public void onLongClick(final int pos, final View v) {
    if (mListener != null && pos >= 0 && pos < mItems.size()) {
      mListener.onLongClick(mItems.get(pos), v);
    }
  }
  @Override
  public int onAudioActionClicked(final int pos, final int progress) {
    if (mListener != null) {
      return mListener.onAudioActionClicked(pos, mItems.get(pos), progress);
    }else {
      return 0;
    }
  }
  @Override
  public void onClick(int pos) {
    if (mItems!=null && pos >= 0 && pos<mItems.size()) {
      Feed feed = mItems.get(pos);
      if (feed != null && mListener != null) {
        mListener.onClick(feed);
      }
    }
  }
  public interface FeedItemListener {
    void toggleLike(@NonNull Feed feed);
    void onLongClick(@NonNull Feed feed, @NonNull View v);
    void onClick(@NonNull Feed feed);
    int onAudioActionClicked(int pos, @NonNull Feed feed, final int progress);
  }
}
FeedHolder:
public class FeedHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
  public static final String SEEK_BAR_PROGRESS_BUNDLE = "bundle_seek_bar_progress";
  public static final String ACTION_ICON_BUNDLE = "bundle_icon";
  public static final String RESET_AUDIO = "bundle_reset_audio";
  private static final int MINE_BG_COLOR = R.color.feed_mine_bg;
  private static final int MINE_TEXT_COLOR = R.color.feed_mine_text;
  private static final int MINE_PLAY_ICON = R.drawable.ic_play_white_24dp;
  private static final int MINE_FILE_ICON = R.drawable.ic_file_white_18dp;
  private static final int THEIR_BG_COLOR = R.color.feed_others_bg;
  private static final int THEIR_TEXT_COLOR = R.color.feed_others_text;
  private static final int THEIR_PLAY_ICON = R.drawable.ic_play_black_24dp;
  private static final int THEIR_FILE_ICON = R.drawable.ic_file_black_18dp;
  private final SimpleDraweeView mAvatar;
  private final TextView mCreator;
  private final TextView mDate;
  private final CardView mCardView;
  private final TextView mText;
  private final TextView mLike;
  private final FeedHolderListener mListener;
  private final SimpleDraweeView mPicture;
  private final int mSize;
  private final View mAudioLayout;
  private final ImageButton mAudioAction;
  private final SeekBar mAudioBar;
  private final TextView mAudioLength;
  public FeedHolder(@NonNull final View itemView, final FeedHolderListener listener, final int size) {
    super(itemView);
    mAvatar = (SimpleDraweeView) itemView.findViewById(R.id.avatar);
    mCreator = (TextView) itemView.findViewById(R.id.creator);
    mDate = (TextView) itemView.findViewById(R.id.date);
    mCardView = (CardView) itemView.findViewById(R.id.card);
    mCardView.setOnLongClickListener(this);
    mCardView.setOnClickListener(this);
    mText = (TextView) itemView.findViewById(R.id.text);
    mLike = (TextView) itemView.findViewById(R.id.like);
    mPicture = (SimpleDraweeView) itemView.findViewById(R.id.picture);
    mLike.setOnClickListener(this);
    mAudioLayout = itemView.findViewById(R.id.audioLayout);
    mAudioAction = (ImageButton) itemView.findViewById(R.id.audioAction);
    mAudioBar = (SeekBar) itemView.findViewById(R.id.audioBar);
    mAudioLength = (TextView) itemView.findViewById(R.id.length);
    mAudioAction.setOnClickListener(this);
    itemView.setOnLongClickListener(this);
    mPicture.setOnLongClickListener(this);
    mPicture.setOnClickListener(this);
    mListener = listener;
    mSize = size;
  }
  @Override
  public void onClick(final View v) {
    int id = v.getId();
    if (id == R.id.like) {
      v.setEnabled(false);
      v.postDelayed(new Runnable() {
        @Override
        public void run() {
          v.setEnabled(true);
        }
      }, 1000);
      if (mListener != null) {
        mListener.toggleLike(getAdapterPosition());
      }
    }else if(id == R.id.audioAction) {
      if (mListener != null) {
        mAudioAction.setImageResource(mListener.onAudioActionClicked(getAdapterPosition(), mAudioBar.getProgress()));
      }
    }else {
      if (mListener != null) {
        mListener.onClick(getAdapterPosition());
      }
    }
  }
  @Override
  public boolean onLongClick(View v) {
    if (mListener != null) {
      mListener.onLongClick(getAdapterPosition(), v);
      return true;
    }else {
      return false;
    }
  }
  public void onBind(@NonNull Feed feed, @NonNull final String userId, final int avatarSize){
    setCreatedBy(feed.getCreatedBy(), avatarSize);
    setCreatedAt(feed.getCreatedAt());
    setLiked(feed.isLiked(userId));
    setLikedCount(feed.getLikedCount());
    boolean mine = feed.getCreatedById().equals(userId);
    setColors(mine);
    switch (feed.getFeedType()) {
      case FEED_COMMENT:
        setText(feed.getShowingText());
        mPicture.setVisibility(View.GONE);
        mAudioLayout.setVisibility(View.GONE);
        break;
      case FEED_IMAGE:
        setText(feed.getCaption());
        setPicture(feed.getUrl(), feed.getPath(), feed.getUri());
        break;
      case FEED_FILE:
        setFile(feed, mine);
        break;
      case FEED_MARKER:
        setMarker();
        break;
      case FEED_AUDIO:
        setAudio(feed.getLength(), mine);
        break;
    }
  }
  public void onBind(@NonNull Feed feed, List<Object> payloads, @NonNull final String userId, final int avatarSize){
    Bundle bundle = (Bundle) payloads.get(0);
    UserResource createdBy = bundle.getParcelable(NAMES.Server.CREATED_BY_ID);
    boolean mine = createdBy != null && createdBy.getUserId().equals(userId);
    for (String key : bundle.keySet()) {
      switch (key) {
        case NAMES.Server.CREATED_AT:
          setCreatedAt(feed.getCreatedAt());
          break;
        case NAMES.Server.CREATED_BY_ID:
          if (createdBy != null) {
            setCreatedBy(createdBy, avatarSize);
            setColors(userId.equals(createdBy.getUserId()));
          }
          break;
        case NAMES.Server.TEXT:
          setText(feed.getShowingText());
          break;
        case NAMES.Server.COUNT:
          setLikedCount(bundle.getInt(NAMES.Server.COUNT, 0));
          break;
        case NAMES.MY_LIKE:
          setLiked(bundle.getBoolean(NAMES.MY_LIKE, false));
          break;
        case NAMES.Server.LENGTH:
          setAudio(bundle.getLong(NAMES.Server.LENGTH, 0), createdBy != null && createdBy.getUserId().equals(userId));
          break;
        case NAMES.Server.PLAN_ID:
          setMarker();
          break;
        case NAMES.Server.CAPTION:
          setText(bundle.getString(NAMES.Server.CAPTION));
          break;
        case NAMES.Server.URL:
        case NAMES.DB.PATH:
          String mimeType = bundle.getString(NAMES.Server.MIME_TYPE);
          if (mimeType != null && mimeType.contains(Constants.MimeType.IMAGE)) {
            setPicture(bundle.getString(NAMES.Server.URL), bundle.getString(NAMES.DB.PATH), null);
          }
          break;
        case SEEK_BAR_PROGRESS_BUNDLE:
          mAudioBar.setProgress(bundle.getInt(SEEK_BAR_PROGRESS_BUNDLE));
          mAudioAction.setImageResource(bundle.getInt(ACTION_ICON_BUNDLE));
          break;
        case RESET_AUDIO:
          resetAudio(bundle.getBoolean("mine"));
          break;
      }
    }
  }
  private void setCreatedBy(UserResource createdBy, final int avatarSize) {
    if (createdBy != null) {
      ImageLoader.newLoad(createdBy.getUrl(), Constants.Thumbnails.T72, mAvatar, avatarSize, avatarSize, R.drawable.unknown_user);
      mCreator.setText(createdBy.getName());
    }
  }
  private void setCreatedAt(@NonNull Date createdAt) {
    mDate.setText(DateUtils.formatDate(createdAt, DateUtils.COMMENT_DATE));
  }
  @SuppressWarnings("deprecation")
  private void setText(String text){
    if (text != null) {
      mText.setVisibility(View.VISIBLE);
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        mText.setText(Html.fromHtml(text.replace("\n", "<br>"), Html.FROM_HTML_MODE_LEGACY), TextView.BufferType.SPANNABLE);
      }else {
        mText.setText(Html.fromHtml(text.replace("\n", "<br>")), TextView.BufferType.SPANNABLE);
      }
    }else {
      mText.setVisibility(View.GONE);
    }
  }
  private void setColors(boolean mine){
    Context context = mCardView.getContext();
    if (mine) {
      mCardView.setBackgroundColor(ContextCompat.getColor(context, MINE_BG_COLOR));
      mText.setTextColor(ContextCompat.getColor(context, MINE_TEXT_COLOR));
      mAudioLength.setTextColor(ContextCompat.getColor(context, MINE_TEXT_COLOR));
    }else {
      mCardView.setBackgroundColor(ContextCompat.getColor(context, THEIR_BG_COLOR));
      mText.setTextColor(ContextCompat.getColor(context, THEIR_TEXT_COLOR));
      mAudioLength.setTextColor(ContextCompat.getColor(context, THEIR_TEXT_COLOR));
    }
  }
  private void setLikedCount(final int count){
    mLike.setText(String.format(Locale.getDefault(), "%d", count));
  }
  private void setLiked(final boolean isLiked){
    if (isLiked) {
      mLike.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_like, 0);
    }else {
      mLike.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_like_empty, 0);
    }
  }
  private void setPicture(final String url, final String path, final Uri uri){
    mAudioLayout.setVisibility(View.GONE);
    if(url != null) {
      mPicture.setVisibility(View.VISIBLE);
      ImageLoader.newLoad(url, Constants.Thumbnails.T480, mPicture, mSize, mSize, R.color.white);
    }else if(path != null){
      mPicture.setVisibility(View.VISIBLE);
      ImageLoader.newLoad(path, mPicture, mSize, mSize, R.color.white);
    }else if (uri != null) {
      mPicture.setVisibility(View.VISIBLE);
      ImageLoader.newLoad(uri, mPicture, mSize, mSize);
    }else {
      mPicture.setVisibility(View.GONE);
    }
  }
  private void setFile(@NonNull final Feed feed, final boolean mine){
    mPicture.setVisibility(View.GONE);
    mText.setVisibility(View.VISIBLE);
    mAudioLayout.setVisibility(View.GONE);
    if (mine) {
      mText.setCompoundDrawablesRelativeWithIntrinsicBounds(MINE_FILE_ICON, 0, 0, 0);
    }else {
      mText.setCompoundDrawablesRelativeWithIntrinsicBounds(THEIR_FILE_ICON, 0, 0, 0);
    }
    mText.setText(feed.getName());
  }
  private void setMarker(){
    mPicture.setVisibility(View.GONE);
    mText.setVisibility(View.VISIBLE);
    mAudioLayout.setVisibility(View.GONE);
    mText.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_plan_gray, 0, 0, 0);
    mText.setText(R.string.feed_marker_placeholder);
  }
  private void setAudio(final long length, final boolean mine){
    mPicture.setVisibility(View.GONE);
    mText.setVisibility(View.GONE);
    mAudioLayout.setVisibility(View.VISIBLE);
    if (mine) {
      mAudioAction.setImageResource(MINE_PLAY_ICON);
    }else {
      mAudioAction.setImageResource(THEIR_PLAY_ICON);
    }
    mAudioLength.setText(AndroidUtils._String.audioLength(length));
    mAudioBar.setMax((int) (length / 1000) * 1000); 
    mAudioBar.setProgress(0);
  }
  public void resetAudio(boolean mine){
    if (mine) {
      mAudioAction.setImageResource(MINE_PLAY_ICON);
      mAudioBar.setProgress(0);
    }else {
      mAudioAction.setImageResource(THEIR_PLAY_ICON);
      mAudioBar.setProgress(0);
    }
  }
  public void setHolderSkeleton(int avatarImageResource, int bgColor){
    mAvatar.setImageResource(avatarImageResource);
    mCreator.setText("");
    mCreator.setBackgroundColor(bgColor);
    mDate.setText("");
    mDate.setBackgroundColor(bgColor);
    mText.setText("");
    mText.setBackgroundColor(bgColor);
    mPicture.setVisibility(View.GONE);
    mAudioLayout.setVisibility(View.GONE);
    mLike.setText("");
    mLike.setBackgroundColor(bgColor);
    mLike.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
  }
  public void clearHolderSkeleton(){
    mCreator.setBackgroundColor(0);
    mDate.setBackgroundColor(0);
    mText.setBackgroundColor(0);
    mLike.setBackgroundColor(0);
  }
  interface FeedHolderListener {
    void toggleLike(final int pos);
    void onLongClick(final int pos, final View v);
    void onClick(final int pos);
    int onAudioActionClicked(final int pos, final int progress);
  }
}