在 Android 如何防止更新 notifyDataSetChanged() 上的现有项目
In Android how to prevent updating existing items on notifyDataSetChanged()
我有聊天应用
在自定义数组适配器中。我使用以下代码为每条消息的用户名设置随机颜色:
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
nameTextView.setTextColor(Color.parseColor(randomColor));
当新消息到达时,我将其添加到列表视图中,然后调用 adapter.notifyDataSetChanged();
这会导致每次重新着色消息中的现有用户名。
调用 adapter.notifyDataSetChanged();
时如何防止重新着色列表视图中的现有项目
编辑 1
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChatMessageElement el = list.get(position);
ViewHolder holder = null;
NewMessagesLabelHolder labelHolder = null;
if (convertView == null) {
convertView = el.getView(inflater, parent);
if (el.isMessage()) {
holder = new ViewHolder();
holder.messageLayout = (RelativeLayout) convertView.findViewById(R.id.message_container);
holder.messageContent = (LinearLayout) convertView.findViewById(R.id.message_content);
holder.bottomIndicator = (LinearLayout) convertView.findViewById(R.id.bottom_indicators);
holder.dateTextView = (TextView) convertView.findViewById(R.id.message_date);
holder.timeAgo = (TextView) convertView.findViewById(R.id.time_ago);
holder.nameTextView = (TextView) convertView.findViewById(R.id.user_name);
holder.likesCountTextView = (TextView) convertView.findViewById(R.id.likes_count);
holder.likesLabelImageView = (ImageView) convertView.findViewById(R.id.likes_label);
holder.spamCountTextView = (TextView) convertView.findViewById(R.id.spam_count);
holder.spamLabelImageView = (ImageView) convertView.findViewById(R.id.spam_label);
holder.avatarImageView = (ImageView) convertView.findViewById(R.id.avatar);
holder.statusImageView = (ImageView) convertView.findViewById(R.id.delivered_label);
holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar);
holder.errorSign = (ImageView) convertView.findViewById(R.id.error_sign);
holder.spamSign = (ImageView) convertView.findViewById(R.id.spam_sign);
holder.bookmarkLabel = (ImageView) convertView.findViewById(R.id.bookmark_label);
holder.topIndicators = (LinearLayout) convertView.findViewById(R.id.topIndicators);
convertView.setTag(holder);
}
if (el.isNewMessagesLabel()) {
convertView = inflater.inflate(R.layout.chat_new_messages_label_layout, parent, false);
labelHolder = new NewMessagesLabelHolder();
labelHolder.newMessagesLabel = (TextView) convertView.findViewById(R.id.new_messages_label);
convertView.setTag(labelHolder);
}
} else {
if (el.isMessage()) {
holder = (ViewHolder) convertView.getTag();
}
if (el.isNewMessagesLabel()) {
labelHolder = (NewMessagesLabelHolder) convertView.getTag();
}
}
if (el.isMessage()) {
Message currentMessage = (Message) el;
drawMessage(holder, currentMessage, position);
}
if (el.isNewMessagesLabel()) {
NewMessagesLabel messagesLabel = (NewMessagesLabel) el;
drawNewMessagesLabel(labelHolder, messagesLabel);
}
return convertView;
}
private void drawMessage(ViewHolder holder, Message message, int position) {
String date = message.getCreatedAt();
String formattedDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "HH:mm", date);
String userName = message.getUserName();
holder.likesLabelImageView.setVisibility(View.GONE);
holder.likesCountTextView.setVisibility(View.GONE);
holder.spamCountTextView.setVisibility(View.GONE);
holder.spamLabelImageView.setVisibility(View.GONE);
holder.bookmarkLabel.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.progressBar.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.errorSign.setVisibility(View.GONE);
holder.spamSign.setVisibility(View.GONE);
holder.timeAgo.setVisibility(View.GONE);
holder.timeAgo.setText("");
holder.messageLayout.setAlpha(1f);
holder.topIndicators.setVisibility(View.VISIBLE);
if (message.isNewDay()) {
holder.timeAgo.setVisibility(View.VISIBLE);
String dayDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "MMMM d, yyyy", date);
//String dayDate = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()), context);
holder.timeAgo.setText(dayDate);
}else{
holder.timeAgo.setVisibility(View.GONE);
}
holder.avatarImageView.setImageResource(R.drawable.com_facebook_profile_default_icon);
if (GrouviDatabaseManager.getInstance(context).getCurrentUser().getId() == message.getUserId()) {
userName = USERNAME_ME;
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SEND)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SENDING)) {
holder.progressBar.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_LOCAL)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() == null || message.getStatus().equals(Message.MSG_STATUS_ERROR)) {
holder.messageLayout.setAlpha(0.4f);
holder.errorSign.setVisibility(View.VISIBLE);
}
}
if (message.getSpamCount() > 0 && currentMode == MODE_NORMAL) {
holder.messageLayout.setAlpha(0.4f);
holder.spamSign.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
holder.spamCountTextView.setText(Integer.toString(message.getSpamCount()));
holder.spamCountTextView.setVisibility(View.VISIBLE);
holder.spamLabelImageView.setVisibility(View.VISIBLE);
} else {
holder.messageLayout.setAlpha(1f);
holder.spamSign.setVisibility(View.GONE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
}
if (currentMode == MODE_REPORT) {
String timeAgo = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()));
holder.timeAgo.setText(timeAgo);
holder.timeAgo.setVisibility(View.VISIBLE);
}
if (message.getUserAvatar() != null && !message.getUserAvatar().isEmpty()) {
try {
Picasso
.with(context)
.load(message.getUserAvatar())
.error(R.drawable.com_facebook_profile_default_icon)
.placeholder(R.drawable.com_facebook_profile_default_icon)
.into(holder.avatarImageView);
} catch (Exception e) {
Log.e("Main", e.getMessage(), e);
}
}
colorUsername(holder, message, userName);
holder.nameTextView.setText(userName);
holder.dateTextView.setText(formattedDate);
if (message.getLikesCount()>0) {
holder.likesCountTextView.setText(Integer.toString(message.getLikesCount()));
holder.likesCountTextView.setVisibility(View.VISIBLE);
holder.likesLabelImageView.setVisibility(View.VISIBLE);
}
if (message.isBookmarked()) {
holder.bookmarkLabel.setVisibility(View.VISIBLE);
}
List<MessageComponent> messageComponentList;
messageComponentList = message.getMessageComponents();
drawMessageContent(holder, messageComponentList, message);
holder.nameTextView.setTag(position);
holder.avatarImageView.setTag(position);
holder.nameTextView.setOnClickListener(userClickListener);
holder.avatarImageView.setOnClickListener(userClickListener);
// hang empty onLingClickListener to display context menu when
// long click on whole message
holder.nameTextView.setOnLongClickListener(longClickListener);
holder.avatarImageView.setOnLongClickListener(longClickListener);
}
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor = prevColor;
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
prevColor = randomColor;
prevMsgUserID = message.getUserId();
}
您应该在数据 class 中保留颜色,例如在 Message class 中,或者在将 Message 映射到 Color 的适配器中保留 Map。然后随机创建一种颜色,当它不存在于地图中时。或者使用颜色,如果它出现在地图中。使用地图是比保留数据 class 更好的解决方案,当颜色与消息无关时,当它不是消息时 属性,所以在这种情况下,一个好的解决方案是保留它在适配器 class 中,在映射中,例如
private Map<Message, String> colorsMap = new HashMap<Message, String>();
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor;
if(colorsMap.contains(message)) {
randomColor = colorsMap.get(message);
}
else {
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
colorsMap.put(message, randomColor);
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
}
基本上您必须创建一个用户数据模型集合。
Like ArrayList<UserModel> arr = new ArrayList<UserModel>();
用户模型可以包含-> userId、userColor、groupId(如果支持群聊)并将此模型映射到您的数据库。
意味着您必须在 db 中创建一个列并在用户 table 中添加 userBgColor 并将其与模型和此模型映射到数组列表中并将数组列表提供给您的自定义适配器。
您可以使用 ORMLite
进行有理映射。
然后在getView()
{
UserModel model = arr.get(position);
String color = user.getUserColor();
}
我有聊天应用 在自定义数组适配器中。我使用以下代码为每条消息的用户名设置随机颜色:
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
nameTextView.setTextColor(Color.parseColor(randomColor));
当新消息到达时,我将其添加到列表视图中,然后调用 adapter.notifyDataSetChanged(); 这会导致每次重新着色消息中的现有用户名。 调用 adapter.notifyDataSetChanged();
时如何防止重新着色列表视图中的现有项目编辑 1
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ChatMessageElement el = list.get(position);
ViewHolder holder = null;
NewMessagesLabelHolder labelHolder = null;
if (convertView == null) {
convertView = el.getView(inflater, parent);
if (el.isMessage()) {
holder = new ViewHolder();
holder.messageLayout = (RelativeLayout) convertView.findViewById(R.id.message_container);
holder.messageContent = (LinearLayout) convertView.findViewById(R.id.message_content);
holder.bottomIndicator = (LinearLayout) convertView.findViewById(R.id.bottom_indicators);
holder.dateTextView = (TextView) convertView.findViewById(R.id.message_date);
holder.timeAgo = (TextView) convertView.findViewById(R.id.time_ago);
holder.nameTextView = (TextView) convertView.findViewById(R.id.user_name);
holder.likesCountTextView = (TextView) convertView.findViewById(R.id.likes_count);
holder.likesLabelImageView = (ImageView) convertView.findViewById(R.id.likes_label);
holder.spamCountTextView = (TextView) convertView.findViewById(R.id.spam_count);
holder.spamLabelImageView = (ImageView) convertView.findViewById(R.id.spam_label);
holder.avatarImageView = (ImageView) convertView.findViewById(R.id.avatar);
holder.statusImageView = (ImageView) convertView.findViewById(R.id.delivered_label);
holder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar);
holder.errorSign = (ImageView) convertView.findViewById(R.id.error_sign);
holder.spamSign = (ImageView) convertView.findViewById(R.id.spam_sign);
holder.bookmarkLabel = (ImageView) convertView.findViewById(R.id.bookmark_label);
holder.topIndicators = (LinearLayout) convertView.findViewById(R.id.topIndicators);
convertView.setTag(holder);
}
if (el.isNewMessagesLabel()) {
convertView = inflater.inflate(R.layout.chat_new_messages_label_layout, parent, false);
labelHolder = new NewMessagesLabelHolder();
labelHolder.newMessagesLabel = (TextView) convertView.findViewById(R.id.new_messages_label);
convertView.setTag(labelHolder);
}
} else {
if (el.isMessage()) {
holder = (ViewHolder) convertView.getTag();
}
if (el.isNewMessagesLabel()) {
labelHolder = (NewMessagesLabelHolder) convertView.getTag();
}
}
if (el.isMessage()) {
Message currentMessage = (Message) el;
drawMessage(holder, currentMessage, position);
}
if (el.isNewMessagesLabel()) {
NewMessagesLabel messagesLabel = (NewMessagesLabel) el;
drawNewMessagesLabel(labelHolder, messagesLabel);
}
return convertView;
}
private void drawMessage(ViewHolder holder, Message message, int position) {
String date = message.getCreatedAt();
String formattedDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "HH:mm", date);
String userName = message.getUserName();
holder.likesLabelImageView.setVisibility(View.GONE);
holder.likesCountTextView.setVisibility(View.GONE);
holder.spamCountTextView.setVisibility(View.GONE);
holder.spamLabelImageView.setVisibility(View.GONE);
holder.bookmarkLabel.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.progressBar.setVisibility(View.GONE);
holder.statusImageView.setVisibility(View.GONE);
holder.errorSign.setVisibility(View.GONE);
holder.spamSign.setVisibility(View.GONE);
holder.timeAgo.setVisibility(View.GONE);
holder.timeAgo.setText("");
holder.messageLayout.setAlpha(1f);
holder.topIndicators.setVisibility(View.VISIBLE);
if (message.isNewDay()) {
holder.timeAgo.setVisibility(View.VISIBLE);
String dayDate = DateHelper.getInstance(context).formatDate("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "MMMM d, yyyy", date);
//String dayDate = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()), context);
holder.timeAgo.setText(dayDate);
}else{
holder.timeAgo.setVisibility(View.GONE);
}
holder.avatarImageView.setImageResource(R.drawable.com_facebook_profile_default_icon);
if (GrouviDatabaseManager.getInstance(context).getCurrentUser().getId() == message.getUserId()) {
userName = USERNAME_ME;
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SEND)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_SENDING)) {
holder.progressBar.setVisibility(View.VISIBLE);
}
if (message.getStatus() != null && message.getStatus().equals(Message.MSG_STATUS_LOCAL)) {
holder.statusImageView.setBackgroundResource(R.drawable.icon_chat_message_delivered);
holder.statusImageView.setVisibility(View.VISIBLE);
}
if (message.getStatus() == null || message.getStatus().equals(Message.MSG_STATUS_ERROR)) {
holder.messageLayout.setAlpha(0.4f);
holder.errorSign.setVisibility(View.VISIBLE);
}
}
if (message.getSpamCount() > 0 && currentMode == MODE_NORMAL) {
holder.messageLayout.setAlpha(0.4f);
holder.spamSign.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
holder.spamCountTextView.setText(Integer.toString(message.getSpamCount()));
holder.spamCountTextView.setVisibility(View.VISIBLE);
holder.spamLabelImageView.setVisibility(View.VISIBLE);
} else {
holder.messageLayout.setAlpha(1f);
holder.spamSign.setVisibility(View.GONE);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
holder.messageContent.setLayoutParams(params);
}
if (currentMode == MODE_REPORT) {
String timeAgo = getTimeAgo(mHelper.millisFromString(message.getCreatedAt()));
holder.timeAgo.setText(timeAgo);
holder.timeAgo.setVisibility(View.VISIBLE);
}
if (message.getUserAvatar() != null && !message.getUserAvatar().isEmpty()) {
try {
Picasso
.with(context)
.load(message.getUserAvatar())
.error(R.drawable.com_facebook_profile_default_icon)
.placeholder(R.drawable.com_facebook_profile_default_icon)
.into(holder.avatarImageView);
} catch (Exception e) {
Log.e("Main", e.getMessage(), e);
}
}
colorUsername(holder, message, userName);
holder.nameTextView.setText(userName);
holder.dateTextView.setText(formattedDate);
if (message.getLikesCount()>0) {
holder.likesCountTextView.setText(Integer.toString(message.getLikesCount()));
holder.likesCountTextView.setVisibility(View.VISIBLE);
holder.likesLabelImageView.setVisibility(View.VISIBLE);
}
if (message.isBookmarked()) {
holder.bookmarkLabel.setVisibility(View.VISIBLE);
}
List<MessageComponent> messageComponentList;
messageComponentList = message.getMessageComponents();
drawMessageContent(holder, messageComponentList, message);
holder.nameTextView.setTag(position);
holder.avatarImageView.setTag(position);
holder.nameTextView.setOnClickListener(userClickListener);
holder.avatarImageView.setOnClickListener(userClickListener);
// hang empty onLingClickListener to display context menu when
// long click on whole message
holder.nameTextView.setOnLongClickListener(longClickListener);
holder.avatarImageView.setOnLongClickListener(longClickListener);
}
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor = prevColor;
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
prevColor = randomColor;
prevMsgUserID = message.getUserId();
}
您应该在数据 class 中保留颜色,例如在 Message class 中,或者在将 Message 映射到 Color 的适配器中保留 Map。然后随机创建一种颜色,当它不存在于地图中时。或者使用颜色,如果它出现在地图中。使用地图是比保留数据 class 更好的解决方案,当颜色与消息无关时,当它不是消息时 属性,所以在这种情况下,一个好的解决方案是保留它在适配器 class 中,在映射中,例如
private Map<Message, String> colorsMap = new HashMap<Message, String>();
private void colorUsername(ViewHolder holder, Message message, String userName) {
String randomColor;
if(colorsMap.contains(message)) {
randomColor = colorsMap.get(message);
}
else {
if (userName.equals(USERNAME_ME)){
randomColor = "#000000";
}else if (message.getUserId()!=prevMsgUserID) {
do {
String[] array = context.getResources().getStringArray(R.array.username_colors);
randomColor = array[new Random().nextInt(array.length)];
}while (prevColor.equals(randomColor));
}
colorsMap.put(message, randomColor);
}
holder.nameTextView.setTextColor(Color.parseColor(randomColor));
}
基本上您必须创建一个用户数据模型集合。
Like ArrayList<UserModel> arr = new ArrayList<UserModel>();
用户模型可以包含-> userId、userColor、groupId(如果支持群聊)并将此模型映射到您的数据库。
意味着您必须在 db 中创建一个列并在用户 table 中添加 userBgColor 并将其与模型和此模型映射到数组列表中并将数组列表提供给您的自定义适配器。
您可以使用 ORMLite
进行有理映射。
然后在getView()
{
UserModel model = arr.get(position);
String color = user.getUserColor();
}