最近要实现一个从蓝牙获取设备名称和地址后,将设备名称重命名并保存的功能,首先用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); //以下为对key和value的具体处理 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; }