【问题标题】:In Android how to prevent updating existing items on notifyDataSetChanged()在 Android 中如何防止更新 notifyDataSetChanged() 上的现有项目
【发布时间】:2015-02-17 08:45:49
【问题描述】:

我有聊天应用 在自定义数组适配器中。我使用此代码为每条消息的用户名设置随机颜色:

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

【问题讨论】:

  • 要为新添加的项目设置哪种颜色?
  • 当您向上滚动列表时,项目的颜色也会发生变化?显示获取视图
  • 是的,滚动它也会改变颜色

标签: android android-arrayadapter


【解决方案1】:

您应该在数据类中保留颜色,例如在 Message 类中,或者在适配器中保留 Map,将 Message 映射到 Color。然后随机创建一种颜色,当它不存在于地图中时。或使用颜色,如果它存在于地图中。与保存在数据类中相比,使用地图是一个很好的解决方案,当颜色与消息无关时,当它不是消息属性时,所以在这种情况下,一个好的解决方案是将它保存在适配器类中,在例如地图

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

【讨论】:

    【解决方案2】:

    基本上你必须创建一个用户数据模型的集合。

    Like ArrayList<UserModel> arr = new ArrayList<UserModel>();
    

    用户模型可以包含-> userId、userColor、groupId(如果支持群聊)并将此模型与您的数据库映射。

    意味着您必须在 db 中创建一个列并在用户表中添加 userBgColor 并将其与模型和此模型映射到数组列表中,并将数组列表提供给您的自定义适配器。

    您可以使用ORMLite 进行理性映射。

    然后在getView()

    {
    
    UserModel model = arr.get(position);
    
    String color = user.getUserColor();
    
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多