列表只滚动时更新 - android listview

时间:2016-06-15 20:34:09

标签: android listview

我正在尝试构建一个使用listview显示消息的聊天应用。我正在使用SignalR进行实时通信。我遇到的问题是,当我滚动时,listview适配器仅更新接收器端的列表,但在发件人端,消息立即显示。 这是聊天的活动:

 protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        ISharedPreferences pref = Application.Context.GetSharedPreferences("UserInfo", FileCreationMode.Private);
        loggeduser = pref.GetString("Username", String.Empty);



        SetContentView(Resource.Layout.chat_activity);

        initControls();
    }

    private async void initControls()
    {
        SignalRClientHelper proxySubscriber = SignalRClientHelper.GetInstance();
        await proxySubscriber.StartConnection();
        proxySubscriber.OnMessageReceived += proxySubscriber_OnMessageReceived;

        messagesContainer = FindViewById<ListView>(Resource.Id.messagesContainer);
        messageET = FindViewById<EditText>(Resource.Id.messageEdit);
        sendBtn = FindViewById<Button>(Resource.Id.chatSendButton);

        adapter = new ChatAdapter(this, new List<ChatMessage>(), loggeduser);
        messagesContainer.Adapter = adapter;

        //loadDummyHistory();

        sendBtn.Click += (o, e) =>
        {
            string messageText = messageET.Text.ToString();
            if (TextUtils.IsEmpty(messageText))
            {
                return;
            }

            proxySubscriber.InvokeSendMessage("psyoptica", messageText);

            ChatMessage chatMessage = new ChatMessage();
            chatMessage.Message = messageText;
            chatMessage.Username = loggeduser;

            messageET.Text = "";

            displayMessage(chatMessage);
        };

        RelativeLayout container = FindViewById<RelativeLayout>(Resource.Id.container);
    }

    void proxySubscriber_OnMessageReceived(string username, string message)
    {
        ChatMessage chatMessage = new ChatMessage { Username = username, Message = message };
        displayMessage(chatMessage);

    }

    public void displayMessage(ChatMessage message)
    {
        adapter.add(message);
        adapter.NotifyDataSetChanged();
        scroll();
    }

    private void scroll()
    {
        messagesContainer.SetSelection(messagesContainer.Count - 1);
    }


}

这里是listview适配器的代码:

class ChatAdapter : BaseAdapter
{
    private List<ChatMessage> messages;
    private Activity context;
    private string loggedUsername;

    public ChatAdapter(Activity context, List<ChatMessage> messages, string loggedUsername)
    {
        this.messages = messages;
        this.context = context;
        this.loggedUsername = loggedUsername;
    }
    public override int Count
    {
        get { return messages.Count; }
    }

    public override Java.Lang.Object GetItem(int position)
    {
        return null;
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view;
        ViewHolder holder;

        if (convertView == null)
        {
            view = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.chatMessage, parent, false);
            holder = createViewHolder(view);
        }
        else
        {
            view = convertView;
            holder = createViewHolder(view);
        }

        bool isMe = messages[position].Username == loggedUsername;

        setAlignment(holder, isMe);

        holder.txtMessage.Text = messages[position].Message;

        return view;
    }

    private void setAlignment(ViewHolder holder, bool isMe)
    {
        if (!isMe)
        {
            holder.contentWithBG.SetBackgroundResource(Resource.Drawable.in_message_bg);

            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)holder.contentWithBG.LayoutParameters;
            layoutParams.Gravity = GravityFlags.Right;
            holder.contentWithBG.LayoutParameters = layoutParams;

            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)holder.content.LayoutParameters;
            lp.AddRule(LayoutRules.AlignParentLeft, 0);
            lp.AddRule(LayoutRules.AlignParentRight);

            holder.content.LayoutParameters = lp;

            layoutParams = (LinearLayout.LayoutParams)holder.txtMessage.LayoutParameters;
            layoutParams.Gravity = GravityFlags.Right;
            holder.txtMessage.LayoutParameters = layoutParams;
        }
        else
        {
            holder.contentWithBG.SetBackgroundResource(Resource.Drawable.out_message_bg);

            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)holder.contentWithBG.LayoutParameters;
            layoutParams.Gravity = GravityFlags.Left;
            holder.contentWithBG.LayoutParameters = layoutParams;

            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)holder.content.LayoutParameters;
            lp.AddRule(LayoutRules.AlignParentRight, 0);
            lp.AddRule(LayoutRules.AlignParentLeft);

            holder.content.LayoutParameters = lp;

            layoutParams = (LinearLayout.LayoutParams)holder.txtMessage.LayoutParameters;
            layoutParams.Gravity = GravityFlags.Left;
            holder.txtMessage.LayoutParameters = layoutParams;
        }
    }

    public void add(ChatMessage message)
    {
        messages.Add(message);
    }

    public void add(List<ChatMessage> chatMessages)
    {
        messages.AddRange(chatMessages);
    }

    private ViewHolder createViewHolder(View v)
    {
        ViewHolder holder = new ViewHolder();
        holder.txtMessage = v.FindViewById<TextView>(Resource.Id.txtMessage);
        holder.content = v.FindViewById<LinearLayout>(Resource.Id.content);
        holder.contentWithBG = v.FindViewById<LinearLayout>(Resource.Id.contentWithBackground);
        holder.txtInfo = v.FindViewById<TextView>(Resource.Id.txtInfo);
        return holder;
    }

    private class ViewHolder
    {
        public TextView txtMessage { get; set; }
        public TextView txtInfo { get; set; }
        public LinearLayout content { get; set; }
        public LinearLayout contentWithBG { get; set; }

    }

}

每次有新消息添加到列表时,都会调用方法displayMessage()。我不明白为什么我必须滚动更改以显示在接收器端。任何人都可以在我的代码中指出错误吗?

1 个答案:

答案 0 :(得分:1)

尝试使用scrollToPosition()而不是setSelection(),并在适配器notifyDataSetChanged()中的add()方法中尝试;

在您的班级ChatAdapter上:

public void add(ChatMessage message)
{ 
    messages.Add(message);
    NotifyDataSetChanged();
}

public void add(List<ChatMessage> chatMessages)
{
    messages.AddRange(chatMessages);
    NotifyDataSetChanged();
}

尝试在proxySubscriber_OnMessageReceived()中运行该进程:

 void proxySubscriber_OnMessageReceived(string username, string message)
{
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     ChatMessage chatMessage = new ChatMessage { Username = username, Message = message };
     displayMessage(chatMessage);
    }
   });


}