2 xkenqq xkenqq 于 2016.03.14 16:15 提问

android 关于listview convertview的一些问题,求解!

图片说明
做的是一个聊天界面,这是adapter代码。
运行时只能输入一次,输第二次时,参数convertview是第二次view的对象,不知道为什么啊。

 package com.example.chattest;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

public class ChatActivity extends Activity implements OnClickListener {
    private Button btnSend;
    private ListView lvChat;
    private EditText etSendContent;
    //聊天内容的适配器
    private ChatMsgViewAdapter chatMsgAdapter;
    //聊天内容
    private List<ChatMsgInfo> chatMsgDataArrays = new ArrayList<ChatMsgInfo>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //不显示标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE); 
        setContentView(R.layout.chat);
        initView();
        initData();
    }

    //初始化视图
    private void initView() {
        lvChat = (ListView) findViewById(R.id.chat_listview);
        btnSend = (Button) findViewById(R.id.btn_send);
        btnSend.setOnClickListener(this);
        etSendContent = (EditText) findViewById(R.id.et_sendmessage); 
    }


    //聊天数据
    //private final static int COUNT = 10
    private String text = new String("第1种写法果然最慢,第二种写法由于用了StringBuffer,快了很多。奇怪的是"
            + "第4种写法竟然也很快,比用StringBuffer还快,怎么回事?其实慢,第二种写"
            + "法由于用了StringBuffer,快了很多。奇怪的是第4种写法竟然也很快,比用StringBuffer还快,怎"
            + "比用StringBuffer还快,怎么回事?其r还快,怎么回事?其回事?其如果你调试过字符串连接的执行过程就会知");
    private String date = new String("2016-3-10 18:11");

    //初始化数据
    private void initData() {
        ChatMsgInfo msgExample = new ChatMsgInfo("XiaoMing", date, text, true);
        chatMsgDataArrays.add(msgExample);
        chatMsgAdapter = new ChatMsgViewAdapter(this, chatMsgDataArrays);
        //listview绑定adapter
        lvChat.setAdapter(chatMsgAdapter);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()) {
        case R.id.btn_send:
            send();
            break;
        }
    }

    //发送按钮的响应函数
    private void send() {
        //获取输入文本框内容
        String sendContent = etSendContent.getText().toString(); 
        if (sendContent.length() > 0) {
            ChatMsgInfo msg = new ChatMsgInfo("XiaoHong", getDate(), sendContent, false);
            chatMsgDataArrays.add(msg);
            //通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容。
            Log.d("chattest", "after setchanged!");
            chatMsgAdapter.notifyDataSetChanged();
            etSendContent.setText("");
            //定位到最后一行
            Log.d("chattest", "after setSelection!");
            lvChat.setSelection(lvChat.getCount() -1 );
        }
    }


    //获取时间
    private String getDate() {
        Calendar c = Calendar.getInstance();
        String year = String.valueOf(c.get(Calendar.YEAR));
        String month = String.valueOf(c.get(Calendar.MONTH));
        String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + 1);
        String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY));
        String mins = String.valueOf(c.get(Calendar.MINUTE));
        StringBuffer buffer = new StringBuffer();
        buffer.append(year + "-" + month + "-" + day + " " + hour + ":" + mins);
        return buffer.toString();
    }
}
 package com.example.chattest;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class ChatMsgViewAdapter extends BaseAdapter {
    private static final int TYPE_COM_MSG = 0;
    private static final int TYPE_TO_MSG = 1;
    //private static final int TAG_KEY_ITEM_TYPE = 0;
    //private static final int TAG_KEY_VIEWHOLDER = 1;

    private List<ChatMsgInfo> data;//数据list
    private LayoutInflater myInflater;//layout convert view对象
    private Context context;//环境

    //构造
    public ChatMsgViewAdapter(Context context, List<ChatMsgInfo> data) {
        this.context = context;
        this.data = data;
        myInflater = LayoutInflater.from(context);
    }

    @Override
    public int getItemViewType(int position) {
        // TODO Auto-generated method stub
        ChatMsgInfo msg = data.get(position);
        if (msg.getMsgType()) {
            return TYPE_COM_MSG;
        } else {
            return TYPE_TO_MSG;
        }
    }

    @Override
    public int getViewTypeCount() {
        // TODO Auto-generated method stub
        return 2;
    }

    //获取ListView的个数
    @Override
    public int getCount() {
        return data.size();
    }

    //获取项
    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    //获取项的id
    @Override
    public long getItemId(int position) {
        return position;
    }

    //获取view
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ChatMsgInfo chatMsg = data.get(position);//聊天数据
        boolean isComMsg = chatMsg.getMsgType();//数据类型(发送、接收)
        LeftItemViewHolder leftViewHolder = null;
        RightItemViewHolder rightViewHolder = null;
        int viewType = getItemViewType(position);
        System.out.println(position + " " + convertView);

        if (convertView == null || ((Integer)convertView.getTag(R.id.tag_item_viewtype)) != viewType) {
            //区分消息类别,展示不同的界面
            if (viewType == TYPE_COM_MSG) {
                convertView = myInflater.inflate(R.layout.chat_msg_text_left_item, null);
                leftViewHolder = new LeftItemViewHolder();
                leftViewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
                leftViewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);
                leftViewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
                leftViewHolder.isComMsg = isComMsg;
                convertView.setTag(R.id.tag_item_viewholder, leftViewHolder);
            } else {
                convertView = myInflater.inflate(R.layout.chat_msg_text_right_item, null);
                rightViewHolder = new RightItemViewHolder();
                rightViewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
                rightViewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
                rightViewHolder.isComMsg = isComMsg;
                convertView.setTag(R.id.tag_item_viewtype, rightViewHolder);
            }
            convertView.setTag(R.id.tag_item_viewtype, viewType);

        } else {
            if (viewType == TYPE_COM_MSG) {
                leftViewHolder = (LeftItemViewHolder) convertView.getTag(R.id.tag_item_viewholder);
            } else {
                rightViewHolder = (RightItemViewHolder) convertView.getTag(R.id.tag_item_viewholder);
            }
        }

        if (viewType == TYPE_COM_MSG) {
            leftViewHolder.tvUserName.setText(chatMsg.getName());
            leftViewHolder.tvSendTime.setText(chatMsg.getDate());
            leftViewHolder.tvContent.setText(chatMsg.getText());
        } else {
            rightViewHolder.tvSendTime.setText(chatMsg.getDate());
            rightViewHolder.tvContent.setText(chatMsg.getText());
        }

        System.out.println(position + " " + convertView);
        return convertView;

    }

    //保存项,显示项的内容
    static class LeftItemViewHolder {
        public TextView tvSendTime;
        public TextView tvUserName;
        public TextView tvContent;
        public boolean isComMsg = true;
    }

    static class RightItemViewHolder {
        public TextView tvSendTime;
        public TextView tvContent;
        public boolean isComMsg = true;
    }
}

5个回答

sjwjay
sjwjay   2016.03.14 16:26

这种问题,一般都是出在适配器上面,你是不是代码贴错了

sjwjay
sjwjay   2016.03.14 16:27

这种问题,一般都是出在适配器上面,你是不是代码贴错了

luochoudan
luochoudan   Ds   Rxr 2016.03.14 17:15

把这句删了试试 ?
convertView.setTag(R.id.tag_item_viewtype, viewType);

xkenqq
xkenqq 为什么我看到的很多例子,复用convert都没有类型判断啊,难道不需要吗?
接近 2 年之前 回复
xkenqq
xkenqq
接近 2 年之前 回复
xkenqq
xkenqq 为什么要删除这句话
接近 2 年之前 回复
lly4321lly
lly4321lly   2016.03.14 18:11

这句什么意思?『运行时只能输入一次,输第二次时,参数convertview是第二次view的对象』是没复用的意思吗?前两次当然不会复用
前面都setTag了,还要这句干嘛?『convertView.setTag(R.id.tag_item_viewtype, viewType);』删掉

lxk_1993
lxk_1993   Rxr 2016.03.14 18:25

if (convertView == null || ((Integer)convertView.getTag(R.id.tag_item_viewtype)) != viewType) {
//区分消息类别,展示不同的界面
if (viewType == TYPE_COM_MSG) {
convertView = myInflater.inflate(R.layout.chat_msg_text_left_item, null);
leftViewHolder = new LeftItemViewHolder();
leftViewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
leftViewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username);
leftViewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
leftViewHolder.isComMsg = isComMsg;
convertView.setTag(R.id.tag_item_viewholder, leftViewHolder);
} else {
convertView = myInflater.inflate(R.layout.chat_msg_text_right_item, null);
rightViewHolder = new RightItemViewHolder();
rightViewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime);
rightViewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent);
rightViewHolder.isComMsg = isComMsg;
convertView.setTag(R.id.tag_item_viewtype, rightViewHolder);
}
convertView.setTag(R.id.tag_item_viewtype, viewType);

                    这里的最后一句删掉
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!