关于自定义对话框加入自定义ListView和getView多次加载导致EditText获取文本的问题

最近要实现一个从蓝牙获取设备名称和地址后,将设备名称重命名并保存的功能,首先用SQLite将蓝牙连接时候获取到的数据添加到数据库中,然后在点击重命名设备控件的时候,弹出一个对话框,并且以ListView的列表形式显示出来。

首先对话框继承于BaseDialog,然后将数据库获取的键值对用ArrayList<HashMap<String,Object>>保存,以参数的形式传到Dialog,并用迭代获取值:

private void initVariable() {
    mAddressList = new ArrayList<String>();
    mNameList = new ArrayList<String>();
    mReNameLsit = new ArrayList<String>();
    it = mReNameDbList.iterator();
    while (it.hasNext()) {
        hash = it.next();
        set = hash.keySet().iterator();
        while (set.hasNext()) {
            key = set.next();
            value = hash.get(key);
            //以下为对keyvalue的具体处理
            mAddressList.add(key);
            mNameList.add(value.toString());

            //根据设备的地址从数据库获取设备的名称
            reNameDbHelper = new ReNameDbHelper(getContext(), value + "", key);
            reName = reNameDbHelper.getReName();
            mReNameLsit.add(reName);
        }
    }
}

我的数据库是用设备地址做索引,所以也用地址做KEY,用迭代的方法把原始名和地址一起传到对话框的ListView中。并将AddressList的长度作为自定义ListView的长度。在ListView中放入左侧EditText修改设备名称,右侧显示名称和地址。

我需要完成的功能主要是点开对话框之后,在每一行的EdtiText中显示当前数据库所有获取过的设备的名称,如果有重命名的显示重命名,没有的则显示原始名称,这里我一开始遇到的最大问题就是监听EditText的值的改变后,会再加载多次getView(),导致我想在EditText完成后直接添加数据到数据库的方法破灭。后来查了很多方法,什么把ListView的高度设置为fill_parent,这个方法我试过,把所有的布局宽高一口气全fill,结果是完全没有效果,所以我放弃了防止多次加载getView的方法,从convertView的Tag来做改动。当监听EditText的before方法执行时给初始化后的EditText设置一个Tag做标记,在EditText监听afterTextChanged的时候判断Tag是否等于position,如果是就可以将数据单次传入数据库而不会反复添加覆盖了。

但是之后又出现了一个问题,就是对话框显示的时候,首先执行设置EditText,然后才会执行监听里面的内容,等EdtiText改变之后,又会再次getView,这样导致一开始假如获取了数据库的重命名,会自动改变EditText的监听,然后马上就将这个值传到数据库,数据库又返回回来,再加上getView的多次加载,导致之后改变的值根本无法存入。后来我就将传值移到了自定义对话框的dismiss()方法中,也就是对话框生命周期中的对话框消失时的方法中。

之后紧接着一个新的问题,一开始加载了重命名,然后改变EditText,由于监听完EditText之后又会执行一次getView,那EditText又会重新将数据库的值再设置过来,因为刚改变之后数据库并没有保存改变后的值,要对话框消失了才会保持,这样导致我刚重命名玩它又加载getView将EditText设置成原先的名称,这样的结果就是,我无论EditText设置多少次,结果都是一样,名称永远都不会改变。

然后我就想到了Tag又可以利用到判断中了,因为第一次创建对话框的时候,是不会执行监听设置Tag的,所以第一次EditText设值的时候Tag是为NULL,这样就可以进行判断,假如Tag为空就是第一次加载,那么之后EditText改变的话不会再重新获取第一次加载数据库的名称来。

getView的详细代码如下:

public View getView(final int position, View convertView, ViewGroup parent) {
    final String dName = mNameList.get(position);
    final String dAddress = mAddressList.get(position);
    final String dReName = mReNameLsit.get(position);

    if (convertView == null) {
        holder = new ViewHolder();
        convertView = layoutInflater.inflate(R.layout.dialog_device_rename_listitem, null);
        holder.deviceName = (TextView) convertView.findViewById(R.id.device_name);
        holder.deviceAddress = (TextView) convertView.findViewById(R.id.device_address);
        holder.deviceNewName = (EditText) convertView.findViewById(R.id.new_name);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    holder.deviceName.setText(dName);
    holder.deviceAddress.setText(dAddress);

    holder.deviceNewName.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            holder.deviceNewName.setTag(position);
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            if ((Integer) holder.deviceNewName.getTag() == position) {
                reNameMap.put(position, s.toString());
            }
        }
    });
    if (holder.deviceNewName.getTag() == null || holder.deviceNewName.getTag().equals("")) {
        if (dReName == null || dReName.equals("")) {
            holder.deviceNewName.setText(dName);
        } else {
            holder.deviceNewName.setText(dReName);
        }
    } else {
        if (reNameMap.get(position) == null || reNameMap.get(position).equals("")) {
            holder.deviceNewName.setText("");
        } else {
            holder.deviceNewName.setText(reNameMap.get(position));
        }
    }
    return convertView;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值