我如何使用带有ListView的复选框并在android中的Sqlite数据库中插入值

时间:2012-12-06 15:27:10

标签: android listview checkbox android-cursoradapter

我正在开发一个Android应用程序,显示手机联系为ListView(使用Cursoradapter)。现在我想向listView添加复选框,我的问题是如何将复选框数据插入数据库,基于是否已选中不是吗?

在我的数据库类中,我有一个用于向我的数据库添加名称和数字的函数,

      createntry(String number,String name) // in my database class

我应该在CursorAdapter类中调用此函数吗?

最近,我发现我应该使用getView函数,但不幸的是我不知道getView,我的问题是

1 - 我应该在My CursorAdapter中使用此功能,否则?

2-如何实现这个功能?

我的CursorAdapterClass

     public class ContactCursorAdapterCT extends CursorAdapter {

         public ContactCursorAdapterCT(Context context, Cursor c) {
    super(context, c);
    }   
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
      TextView name = (TextView)view.findViewById(R.id.contactlistTV1);      
          name.setText(cursor.getString
          (cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
          TextView phone = (TextView)view.findViewById(R.id.contactlistTV2);                
           phone.setText(cursor.getString          
          (cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) { 
    LayoutInflater inflater = LayoutInflater.from(context);
    View v = inflater.inflate(R.layout.lvct, parent, false);
            bindView(v, context, cursor);
    return v;

}

public View getView(final int pos, View inView, ViewGroup parent) { //getView 

    }

我的活动课

   public class Contacts extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.contacts);

    Cursor cursor = getContentResolver().query
            (ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,null, null);
        startManagingCursor(cursor);
           ContactCursorAdapterCT adapter= new ContactCursorAdapterCT
           (Contacts.this, cursor);
       ListView contactLV = (ListView) findViewById(R.id.listviewblcontactsDB);
           contactLV.setAdapter(adapter);

我的数据库类

  public long creatEntry(String inputnumber , String name) { // for add data   

    // TODO Auto-generated method stub
    ContentValues cv= new ContentValues();
    cv.put(KEY_NUMBER, inputnumber);
    cv.put(N_NAME, name);
    Log.v(inputnumber, "adding to Database");
    return ourdatabase.insert(DATABASE_TABLE, null, cv);
 } 

2 个答案:

答案 0 :(得分:3)

首先,不,你不需要getViewbindViewnewView一起完全足以取代它,有些人可能会说更好。而且,您不需要在新视图中调用bindview。这是对应该存在的重组。

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
        View v = inflater.inflate(R.layout.lvct, parent, false);
        return v;
    } 

这完全是你的电话,但我不认为你应该将createEntry方法放入适配器,至少在它的方法中。问题是适配器中的方法是为listview的每一行调用的,所以你可能会有很多冗余的事情发生,而且我个人发现将数据插入到数据库中是很浪费的。相反,我认为你有没有选择但是要一次完成所有这些,因为如果有人取消选中复选框怎么办?你删除你的条目?不仅浪费,而且跟踪光标位置或_id太麻烦,每次添加某些内容时都需要重新查询。你应该做的是维护一个需要添加到数据库的列表,并在完成后批量插入。

首先,您需要创建一个包含要插入的数据的对象。对象是最简洁的方法,因为您需要保存多条信息。这里非常简单,您可以将所需的值插入构造函数中,然后使用getter方法进行检索。

public class ContactObject {

    private String name;
    private String phone;

    public ContactObject(String name, String phone) {
        super();
        this.name = name;
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public String getPhone() {
        return phone;
    }
}

现在,您需要一个对象来检查这些对象。我知道这很奇怪,但是如果它们被识别并且可以迭代并且通常被批处理以进行参考则更加方便。我认为这种任务需要HashMap。在构造函数中创建它。

contactMap = new HashMap<Integer, ContactObject>(c.getCount());

现在是时候去布吉了。为复选框创建方法,以添加和删除HashMap中的内容。

cbInsert.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    if (cbInsert.isChecked()) {
                        contactMap.put(cursor.getPosition(), new ContactObject(str_name, str_phone));
                    } else {
                        contactMap.remove(cursor.getPosition());
                    }
                }
            });

我们在HashMap中使用了光标位置,就像我们对象的id一样。当取消选中我们的复选框并且我们要删除放入的对象时,我们可以引用我们使用的那个标识符。更谨慎的人可能想要在移除之前检查位置是否存在某些东西,这由您自行决定。现在我们差不多完成了。我们如何将HashMap转换为数据库中的条目?您必须访问数据库对象,循环然后逐个访问您的对象。现在的问题是在哪里。你可以在适配器中做到这一点,但我通常在我的活动中做这样的事情,因为在我的情况下我通常有一个数据库已经为其他任务的活动做了,我不喜欢制作比我更多的对象推到。所以,我们可以做的是在我们的HashMap适配器中使用getter方法完成:

    public HashMap<Integer, ContactObject> getContactMap() {
        return contactMap;
    }   

现在我想你在你的应用程序离开时会做这样的事情,所以这里就是这样。

@Override
protected void onDestroy() {
    super.onDestroy();
    HashMap<Integer, ContactObject> contactMap = adapter.getContactMap();
    DatabaseHelper db = new DatabaseHelper(this);
    // iterate through hashmap
    for (Map.Entry<Integer, ContactObject> entry : contactMap.entrySet()) {
        Integer key = entry.getKey();
        ContactObject value = entry.getValue();

        db.creatEntry(key, value.getPhone(), value.getName());
    }
    db.close();
}

现在事情看起来有点奇怪,我的入门方法是怎么回事?

public long creatEntry(Integer id, String inputnumber, String name) { // for add data
        long lng;
        String strId = id.toString();
        String[] selectionArgs = {strId};
        Cursor cursor = ourdatabase.query(DATABASE_TABLE, null, "other_id = ?", selectionArgs, null, null, null);
        if (cursor.moveToFirst()) {
            // it exists, i'd assume that you might not want anything else done here
            lng = -1;
        } else {
            // it doesn't exist
            ContentValues cv= new ContentValues();
            cv.put(KEY_NUMBER, inputnumber);
            cv.put(N_NAME, name);
            cv.put(KEY_OTHERID, strId);
            Log.v(inputnumber, "adding to Database");  
            lng = ourdatabase.insert(DATABASE_TABLE, null, cv);
        }
//      cursor.close();
        return lng;
    } 

你可以看到我修改它以便它也包含id。我认为你遇到的问题是你的数据库中有重复。我认为你可以通过另一个字段为你可以修改的id来管理它。这个id指的是从HashMap传入的id。我想每次进行插入时,首先要检查先前的ID是否存在,然后决定你想做什么。这不是一个完美的解决方案,但我只是想提醒您这个问题是可能的,并提供一个可能的提示来管理它。一般来说,如果你只想插入几行,插入方法应该没问题,但如果要插入很多东西,你可能需要查看批量交易以获得性能。

还有一件事,列表视图中的复选框不能像往常期望的那样保持其状态。您必须明确指出复选框在每个位置的状态。如果您的HashMap已经填充了相应的键,我就会对应它。这是完整的适配器方法,希望它更清晰:

public class ContactCursorAdapterCT extends CursorAdapter {

        private LayoutInflater inflater;
        private HashMap<Integer, ContactObject> contactMap;

        public ContactCursorAdapterCT(Context context, Cursor c) {
            super(context, c);
            inflater = LayoutInflater.from(context);
            contactMap = new HashMap<Integer, ContactObject>(c.getCount());
            // i used c.getCount() as a capacity limit for this.
            // if you opened made this multiple times, it might get over inflated and 
            // slow things down.
        }   

        @Override
        public void bindView(View view, Context context, final Cursor cursor) {
            TextView name = (TextView)view.findViewById(R.id.contactlistTV1);
            TextView phone = (TextView)view.findViewById(R.id.contactlistTV2);
            final CheckBox cbInsert = (CheckBox) view.findViewById(R.id.contactlistCB1);

            String str_name = cursor.getString
                    (cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String str_phone = cursor.getString          
                    (cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

            name.setText(str_name);
            phone.setText(str_phone);

            boolean isFilled = contactMap.containsKey(cursor.getPosition());
            cbInsert.setChecked(isFilled);

            // insert, remove objects to hashmap
            cbInsert.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    if (cbInsert.isChecked()) {
                        contactMap.put(cursor.getPosition(), new ContactObject(str_name, str_phone));
                    } else {
                        contactMap.remove(cursor.getPosition());
                    }
                }
            });         

        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) { 
            View v = inflater.inflate(R.layout.lvct, parent, false);
            return v;
        }

        public HashMap<Integer, ContactObject> getContactMap() {
            return contactMap;
        }
    }

答案 1 :(得分:0)

最好在记录中添加一个标志,表明它们已经过检查。这意味着条目将具有名称,数字和标志(已选中/未选中)。

Adapter本身,您可以相应地检查此标志的值。

(相关答案是关于ListView中的复选框here