Android CursorAdapter在错误的列表项中绘制东西

moo*_*ese 2 android android-listview android-adapter

我有一个CursorAdapter是从数据库构建的Cursor,如果View第一个项目中没有填写,它会填充第一个项目的Views,View其中包含View设置的第一个后续列表项中的数据.另外,我发现onBindView每个列表项都会触发三次,这看起来很奇怪.它只对第一个列表项执行此操作,而不是对所有具有null Views 的项执行此操作.这是它的样子:

例

请注意,"Julian"的地址已复制到"Alice".每当我在onBindView方法中设置一个断点时,我可以看到当customerName是"Alice Martin"时,if(billingAddressCursor!=null && billingAddressCursor.getCount()>0)对于所有三次调用,总是评估为false onBindView,所以我知道它永远不会进入计费条件.

为什么它在第一个位置绘制错误的值并且如何阻止它?码:

private class CustomerAdapter extends CursorAdapter {
    /*** DEBUG CODE, TO BE REMOVED ***/
    int aliceBindCount = 0;
    int blakeBindCount = 0;
    int cscBindCount = 0;
    int julianBindCount = 0;
    /*** ^^^^^^^^^^^^^^^^^^^^^^^^^ ***/
    public CustomerAdapter(Context context, Cursor cursor) {
        super(context, cursor);
    }

    public void bindView(View convertView, Context context, Cursor cursor) {
        if(convertView!=null) {
            String customerName = cursor.getString(cursor.getColumnIndex(CustomerSchema.NAME));
            ((TextView)convertView.findViewById(R.id.cli_customer_name)).setText(customerName);
            /*** DEBUG CODE, TO BE REMOVED ***/
            if(customerName.equals("Alice Martin")) {
                aliceBindCount += 1;
            } else if(customerName.equals("Blake Slappey")) {
                blakeBindCount += 1;
            } else if(customerName.equals("Conceptual Systems")) {
                cscBindCount += 1;
            } else if(customerName.equals("Julian")) {
                julianBindCount += 1;
            }
            /*** ^^^^^^^^^^^^^^^^^^^^^^^^^ ***/
        }
        final Long billingAddressID = cursor.getLong(cursor.getColumnIndex(CustomerSchema.BILLING_ADDRESS_ID));
        Cursor billingAddressCursor = DbDesc.getInstance().getDatabase(getActivity()).query(
                LocationSchema.TABLE_NAME,
                null,
                LocationSchema._ID+"=?",
                new String[]{ String.valueOf(billingAddressID) },
                null,
                null,
                null
        );
        if(billingAddressCursor!=null && billingAddressCursor.getCount()>0) {
            billingAddressCursor.moveToFirst();
            String street = billingAddressCursor.getString(billingAddressCursor.getColumnIndex(LocationSchema.STREET));
            String city = billingAddressCursor.getString(billingAddressCursor.getColumnIndex(LocationSchema.CITY));
            String state = billingAddressCursor.getString(billingAddressCursor.getColumnIndex(LocationSchema.STATE));
            String zip = billingAddressCursor.getString(billingAddressCursor.getColumnIndex(LocationSchema.ZIP));
            if(zip==null || zip.equals("")) {
                zip = "[NO ZIP]";
            }
            if(street==null || street.equals("")) {
                street = "[NO STREET]";
            }
            if(city==null || city.equals("")) {
                city = "[NO CITY]";
            }
            if(state==null || state.equals("")) {
                state = "[NO STATE]";
            }
            ((TextView)convertView.findViewById(R.id.cli_street)).setText(street);
            ((TextView)convertView.findViewById(R.id.cli_city_state_zip)).setText(city+", "+state+" "+zip);
        }
    }

    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(R.layout.customer_list_item, parent, false);
        return v;
    }
}
Run Code Online (Sandbox Code Playgroud)

我确信Alice不应该有与该记录相关联的帐单邮寄地址.这是sqlite3的表查询.唯一具有帐单邮寄地址ID的记录是Julian的记录,如您所见:

sqlite> .tables
.tables
android_metadata  contract          location
contact           customer          phone
sqlite> select * from customer;
select * from customer;
2|Conceptual Systems|||||||
3|Blake Slappey|||||||
4|Julian|1||||||
5|Alice Martin|||||||
Run Code Online (Sandbox Code Playgroud)

stu*_*ess 5

从看代码(这是在第一次有点混乱),似乎你有一个自定义CursorAdaptercustomer和内部的bindView()该适配器,你正在做二次查询的location那个人(即从加入customerlocation).这将会表现不佳,因为在UI线程上,对于每个客户,您正在进行二次查询.

难道这是使用更容易解决SimpleCursorAdapter之间的连接查询customerlocation.(在我看来,自定义适配器的唯一目的是做的"加入" customer,并location在一个非常低效的方式)

这样,查询将在backgound中发生,Loaders或许使用,并且绑定将相当有效,从不需要执行备用查询.

初始查询可能类似于..

select customer.name, location.address1, location.address2 from customer, location where customer.location_id = location._id
Run Code Online (Sandbox Code Playgroud)

(我不确定你的字段名称是什么,但希望传达基本结构)