简体   繁体   中英

Where to manipulate the data in Recyclerview Adapter (Android)

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 onBindViewHolder method

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.

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;
    }
}

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

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.
    }
  }
}

Just Use SimpleDateFormat with yyyy-MM-dd pattern .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM