Where to manipulate the data in Recyclerview Adapter (Android)

custom recyclerview android example
androidx recyclerview
simple recyclerview android example
android-recyclerview get item view at position
recyclerview adapter kotlin
android recyclerview add item dynamically
androidx recyclerview example
android recyclerview dependency

My datetime is currently stored as UNIX time stamp. I want to display it as h:mm a in my Recyclerview.

Where should I convert the UNIX time stamp into normal time in the RecyclerView Adapter/Viewholder (in terms of the best performance)?

Should I do it in the getItemViewType(int position) of the RecyclerView.Adapter, or the onBindViewHolder or the bind function of the ViewHolder class?

Edit: My code

public class ChatListAdapter extends RecyclerView.Adapter {


    private final LayoutInflater mInflater;
    private List<Chat> mChats;
    private final String ownerMe = "OWNER_ME";
    private static final int VIEW_TYPE_MESSAGE_ME = 1;
    private static final int VIEW_TYPE_MESSAGE_ME_CORNER = 2;
    private static final int VIEW_TYPE_MESSAGE_BF = 3;
    private static final int VIEW_TYPE_MESSAGE_BF_CORNER = 4;

    ChatListAdapter(Context context) {mInflater = LayoutInflater.from(context);}

    @Override
    public int getItemViewType(int position) {
        Chat chat = mChats.get(position);

        if(chat.getUser().equals(ownerMe)) {
            if(position == mChats.size()-1) {
                return VIEW_TYPE_MESSAGE_ME_CORNER;
            }
            if(chat.getUser().equals(mChats.get(position+1).getUser())) {
                return VIEW_TYPE_MESSAGE_ME;
            } else {
                return VIEW_TYPE_MESSAGE_ME_CORNER;
            }
        } else {
            if(position == mChats.size()-1) {
                return VIEW_TYPE_MESSAGE_BF_CORNER;
            }
            if(chat.getUser().equals(mChats.get(position+1).getUser())) {
                return VIEW_TYPE_MESSAGE_BF;
            } else {
                return VIEW_TYPE_MESSAGE_BF_CORNER;
            }
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;

        if(viewType == VIEW_TYPE_MESSAGE_ME || viewType == VIEW_TYPE_MESSAGE_ME_CORNER) {
            view = mInflater.inflate(R.layout.recyclerview_item_right, parent, false);
            return new MeMessageHolder(view);
        } else if (viewType == VIEW_TYPE_MESSAGE_BF || viewType == VIEW_TYPE_MESSAGE_BF_CORNER) {
            view = mInflater.inflate(R.layout.recyclerview_item_left, parent, false);
            return new BfMessageHolder(view);
        }
        return null;

    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (mChats != null) {
            Chat current = mChats.get(position);
            long unixTime= current.getUnixTime();
            Date time = new java.util.Date(unixTime*1000L);
            SimpleDateFormat sdf = new java.text.SimpleDateFormat("h:mm a");
            String formattedTime = sdf.format(time);

            switch (holder.getItemViewType()) {
                case VIEW_TYPE_MESSAGE_ME:
                    ((MeMessageHolder) holder).bind(current, formattedTime, false);
                    break;
                case VIEW_TYPE_MESSAGE_ME_CORNER:
                    ((MeMessageHolder) holder).bind(current, formattedTime, true);
                    break;
                case VIEW_TYPE_MESSAGE_BF:
                    ((BfMessageHolder) holder).bind(current, formattedTime, false);
                    break;
                case VIEW_TYPE_MESSAGE_BF_CORNER:
                    ((BfMessageHolder) holder).bind(current, formattedTime, true);
                    break;
            }
        }
    }

    class MeMessageHolder extends RecyclerView.ViewHolder {
        private final TextView chatItemView;
        private final ImageView cornerRightIImageView;
        private final ConstraintLayout constraintLayout;
        private final TextView timeItemView;


        private MeMessageHolder(View itemView) {
            super(itemView);
            chatItemView = itemView.findViewById(R.id.textView);
            cornerRightIImageView = itemView.findViewById(R.id.corner_view_right);
            constraintLayout = itemView.findViewById(R.id.chat_bubble_id);
            timeItemView = itemView.findViewById(R.id.text_message_time);

        }

        void bind(Chat chat, String formattedTime, boolean isCorner) {
            chatItemView.setText(chat.getMessage());
            timeItemView.setText(formattedTime);
            if(isCorner) {
                constraintLayout.setBackgroundResource(R.drawable.chat_bubble_v2);
            } else {
                cornerRightIImageView.setVisibility(View.INVISIBLE);
            }
        }
    }

    class BfMessageHolder extends RecyclerView.ViewHolder {
        private final TextView chatItemView;
        private final ImageView cornerLeftImageView;
        private final ConstraintLayout constraintLayout;
        private final TextView timeItemView;

        private BfMessageHolder(View itemView) {
            super(itemView);
            chatItemView = itemView.findViewById(R.id.textView);
            cornerLeftImageView = itemView.findViewById(R.id.corner_view_left);
            constraintLayout = itemView.findViewById(R.id.chat_bubble_id);
            timeItemView = itemView.findViewById(R.id.text_message_time);
        }

        void bind(Chat chat, String formattedTime, boolean isCorner) {
            chatItemView.setText(chat.getMessage());
            timeItemView.setText(formattedTime);
            if(isCorner) {
                constraintLayout.setBackgroundResource(R.drawable.chat_bubble_v3);
            } else {
                cornerLeftImageView.setVisibility(View.INVISIBLE);
            }
        }
    }

    void setChats(List<Chat> chats) {
        mChats = chats;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        if(mChats!=null)
            return mChats.size();
        else return 0;
    }
}

This is method correct? I formatted the date in the onBindViewHoldermethod

It seems like business logic. So, i recommend to move you UNIX time stamp convertation in Model for example.

class Chat {

   private Long unixTime;

   // another code

   public Long getUnixTime() {
      return unixTime;
   }

   public String convertedUnixTimeToString(String format) {
      // Also need to add some format validation     
      if(format == null) {
         // do some action, like trowing exception, or setting default value in format
      } 

      Date time = new java.util.Date(unixTime*1000L);
      SimpleDateFormat sdf = new java.text.SimpleDateFormat(format);

      return sdf.format(time);
   }

}

I recommend you to use JodaTime for date&time formatting. Very useful thing.

And then, just modify your code

public class ChatListAdapter extends RecyclerView.Adapter {


    private final LayoutInflater mInflater;
    private List<Chat> mChats;
    private final String ownerMe = "OWNER_ME";
    private static final int VIEW_TYPE_MESSAGE_ME = 1;
    private static final int VIEW_TYPE_MESSAGE_ME_CORNER = 2;
    private static final int VIEW_TYPE_MESSAGE_BF = 3;
    private static final int VIEW_TYPE_MESSAGE_BF_CORNER = 4;

    ChatListAdapter(Context context) {mInflater = LayoutInflater.from(context);}

    @Override
    public int getItemViewType(int position) {
        Chat chat = mChats.get(position);

        if(chat.getUser().equals(ownerMe)) {
            if(position == mChats.size()-1) {
                return VIEW_TYPE_MESSAGE_ME_CORNER;
            }
            if(chat.getUser().equals(mChats.get(position+1).getUser())) {
                return VIEW_TYPE_MESSAGE_ME;
            } else {
                return VIEW_TYPE_MESSAGE_ME_CORNER;
            }
        } else {
            if(position == mChats.size()-1) {
                return VIEW_TYPE_MESSAGE_BF_CORNER;
            }
            if(chat.getUser().equals(mChats.get(position+1).getUser())) {
                return VIEW_TYPE_MESSAGE_BF;
            } else {
                return VIEW_TYPE_MESSAGE_BF_CORNER;
            }
        }
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;

        if(viewType == VIEW_TYPE_MESSAGE_ME || viewType == VIEW_TYPE_MESSAGE_ME_CORNER) {
            view = mInflater.inflate(R.layout.recyclerview_item_right, parent, false);
            return new MeMessageHolder(view);
        } else if (viewType == VIEW_TYPE_MESSAGE_BF || viewType == VIEW_TYPE_MESSAGE_BF_CORNER) {
            view = mInflater.inflate(R.layout.recyclerview_item_left, parent, false);
            return new BfMessageHolder(view);
        }
        return null;

    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (mChats != null) {
            Chat current = mChats.get(position);

            switch (holder.getItemViewType()) {
                case VIEW_TYPE_MESSAGE_ME:
                    ((MeMessageHolder) holder).bind(current, false);
                    break;
                case VIEW_TYPE_MESSAGE_ME_CORNER:
                    ((MeMessageHolder) holder).bind(current, true);
                    break;
                case VIEW_TYPE_MESSAGE_BF:
                    ((BfMessageHolder) holder).bind(current, false);
                    break;
                case VIEW_TYPE_MESSAGE_BF_CORNER:
                    ((BfMessageHolder) holder).bind(current, true);
                    break;
            }
        }
    }

    class MeMessageHolder extends RecyclerView.ViewHolder {
        private final TextView chatItemView;
        private final ImageView cornerRightIImageView;
        private final ConstraintLayout constraintLayout;
        private final TextView timeItemView;


        private MeMessageHolder(View itemView) {
            super(itemView);
            chatItemView = itemView.findViewById(R.id.textView);
            cornerRightIImageView = itemView.findViewById(R.id.corner_view_right);
            constraintLayout = itemView.findViewById(R.id.chat_bubble_id);
            timeItemView = itemView.findViewById(R.id.text_message_time);

        }

        void bind(Chat chat, boolean isCorner) {
            chatItemView.setText(chat.getMessage());
            timeItemView.setText(chat.convertedUnixTimeToString("h:mm a"));
            if(isCorner) {
                constraintLayout.setBackgroundResource(R.drawable.chat_bubble_v2);
            } else {
                cornerRightIImageView.setVisibility(View.INVISIBLE);
            }
        }
    }

    class BfMessageHolder extends RecyclerView.ViewHolder {
        private final TextView chatItemView;
        private final ImageView cornerLeftImageView;
        private final ConstraintLayout constraintLayout;
        private final TextView timeItemView;

        private BfMessageHolder(View itemView) {
            super(itemView);
            chatItemView = itemView.findViewById(R.id.textView);
            cornerLeftImageView = itemView.findViewById(R.id.corner_view_left);
            constraintLayout = itemView.findViewById(R.id.chat_bubble_id);
            timeItemView = itemView.findViewById(R.id.text_message_time);
        }

        void bind(Chat chat, boolean isCorner) {
            chatItemView.setText(chat.getMessage());
            timeItemView.setText(chat.convertedUnixTimeToString("h:mm a"));
            if(isCorner) {
                constraintLayout.setBackgroundResource(R.drawable.chat_bubble_v3);
            } else {
                cornerLeftImageView.setVisibility(View.INVISIBLE);
            }
        }
    }

    void setChats(List<Chat> chats) {
        mChats = chats;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        if(mChats!=null)
            return mChats.size();
        else return 0;
    }
}

Using the RecyclerView, The RecyclerView is a ViewGroup that renders any adapter-based view in a similar way. Adapter - To handle the data collection and bind it to the view Finally, we need to modify the onBindViewHolder to use the getItem() method instead. RecyclerView.Adapter. The RecyclerView.Adapter, much like the built-in Android ArrayAdapter, will populate the data into the RecyclerView. It also converts a Java object into an individual list item View to be inserted and displayed to the user. Let's look at this image one more time, as we are about to build something very similar:

It depends whether you want to display different dates on different items of the recyclerview, or the same date on all items of the recyclerview. If you want to show same date to all items, better to do it outside of the adapter and then pass the parsed date to the recyclerview adapter. Or, if you want to show different dates on each item, you should do it inside onBindViewHolder as it has access to the item position.

Remember, getItemViewType is used for getting a view type out of the available ones. This is used in case you are inflating multiple views. Think of a chatapp where view1 will display message on the left, and view2 will display message on the right; all within the same recyclerview.

The onBindViewHolder method simply performs a generic binding task. Binds what : the item of the inflated view and the data.

Create a List with RecyclerView, Using RecyclerView to display lists and grids of dynamic content. The adapter also binds the view holders to their data. It does this by assigning You retain control over the visual presentation of a selected item. You can� The layout manager then binds the view holder to its data. It does this by calling the adapter's onBindViewHolder() method, and passing the view holder's position in the RecyclerView. The onBindViewHolder() method needs to fetch the appropriate data, and

You need to convert it to milliseconds by multiplying the timestamp by 1000:

java.util.Date dateTime=new java.util.Date((long)timeStamp*1000);

then first you need to convert UNIX timestamp to datetime format

final long unixTime = 1372339860;
final String formattedDtm = Instant.ofEpochSecond(unixTime)
        .atZone(ZoneId.of("GMT-4"))
        .format(formatter);

System.out.println(formattedDtm);   // => '2013-06-27 09:31:00'

then you want to store this data to field value of RecyclerView then you can format it from this time format like h:mm

Android Fundamentals: Working with the RecyclerView, Adapter , A Simple RecyclerView / Adapter / ViewHolder Pattern handle all data manipulation outside of our adapter in our SimpleViewModel class. Android Official Documentation provided a tutorial for creating a RecyclerView in Activity. However, it is a bit different when trying to create a RecyclerView in Fragment instead. Open Android…

You should be updating the UI changes in onBindViewHolder method. You can call bind method of ViewHolder in onBindViewHolder.

Example:

public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {

  @NonNull
  @Override
  public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sample_view, viewGroup, false);
    return new ViewHolder(view);
  }

  @Override
  public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
    viewHolder.bind(i);
  }

  public class ViewHolder extends RecyclerView.ViewHolder {

    public ViewHolder(@NonNull View itemView) {
      super(itemView);
    }

    void bind(int position) {
      // Do your data updates here.
    }
  }
}

Android Recycler View. The advanced enhancement of…, Android recyclerview is the most advanced version of the listview. basically, Create a model class for data manipulation with the getters and setters.in here I� This post will hopefully help you with that as you are learning how to update the adapter data in an Android RecyclerView. If you need help setting up the RecyclerView itself, then see this post

Just Use SimpleDateFormat with yyyy-MM-dd pattern .

Apply SimpleDateFormat.format(millis) in onBindViewHolder method of RecyclerView.

RecyclerView in Android with Example, You can use RecyclerView widget when you have data collections whose The adapter could //, for example, control the power output by� In this android kotlin source code example, we are going to use notifyDatasetChanged() RecyclerView Adapter in Kotlin. You can copy and adopt this source code example to your Kotlin android project without reinventing the wheel. Below is a step by step source code to use notifyDatasetChanged() RecyclerView Adapter in Kotlin.

Implement your first RecyclerView, Adapter): Used to bind the RecyclerView and a list of data. We start by installing the Android supporting library, adding the RecyclerView with our Next, we created a public method that will enable us to modify this view� An adapter can use multiple ViewHolder classes to hold headers and various types of data. You can have exactly one view holder for data, and one view holder for a header. A RecyclerView supports multiple types of headers, but the data has to be uniform.

4.5: RecyclerView � GitBook, For LinearLayout , the Android system handles the layout for you. RecyclerView requires an explicit In a RecyclerView , the adapter connects data with View items. It acts as an Right-click (or Control-click) the TextView . Choose Refactor �

Android RecyclerView List Example, Android RecyclerView List with examples of Activity and Intent, Fragments, Menu, It is an advanced version of the ListView with improved performance and the user interface with the fine-grain control over the lists and grids of android application. Create a dimens.xml file in values directory, and add the following code.

Comments
  • I believe onBindViewHolder is the right place to populate it.
  • Do on onBindViewHolder method.
  • @bulbasarous You are welcome. Can you add plus to answer and mark it aswer like question resolver?)
  • Okay thank you! So once the date has been manipulated inside the onBindViewHolder, I have to pass it into the Bind method? I've posted my updated code above
  • So to clarify, any manipulation of data should be done in the void bind(int position){} function?
  • If you are updating the UI then you should be doing it in onBindViewHolder bind function. If you want to manipulate the existing data in the List, then it should be done prior loading it to RecyclerView. This way it'll be performance efficient.
  • Okay thank you! I was curious about which one was more efficient.
  • @AmitKumar vote his question please, if you think that question is good))