1

I'm developing an android app which shows phone contact as ListView(used Cursoradapter).Now I Want to add checkbox to the listView ,My problem is How to Insert checkbox data into database, based on if it is checked or not?

In my database class, I have a function which use to add names and numbers to my database,

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

Should I invoke this function in my CursorAdapter class ?

Recently, I found out that I should use getView function,but unfortunately I have no idea about getView, My question are

1-I should use this function in My CursorAdapter or else?

2- how to implement this function?

My 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 

    }

My activity class

   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);

My database Class

  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);
 } 
4

2 回答 2

3

首先,不,你不需要getView. bindView结合 withnewView完全可以替代它,有些人可能会说更好。此外,您不需要在新视图中调用 bindview。这是对应该存在的内容的重组。

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

这完全是您的电话,但不,我不认为您应该将您的createEntry方法放入适配器中,至少在其方法中。问题是适配器中的方法会为您的列表视图的每一行调用,因此您可能会冗余地发生很多事情,而且我个人认为以增量方式插入数据库是浪费的。相反,我认为您别无选择,只能一次完成所有操作,因为如果有人取消选中复选框怎么办?你删除你的条目?不仅浪费,而且跟踪光标位置也太麻烦,或者_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());
                    }
                }
            });

我们将光标位置用作对象的 idHashMap. 当我们的复选框未选中并且我们想要删除放入的对象时,我们可以引用我们使用的那个标识符。更谨慎的人可能想在移除之前检查该位置是否有东西,这由您自行决定。现在我们差不多完成了。我们如何将我们的 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 是否存在,然后决定您想要做什么。这不是一个完美的解决方案,但我只是想提醒您该问题是可能的,并给出管理它的可能提示。一般来说,如果您只想插入几行,插入方法应该没问题,但如果您有很多东西要插入,您可能想研究批量事务以提高性能。

还有一件事,不能期望您的列表视图中的复选框的状态会像您通常期望的那样持续存在。您必须明确规定复选框在每个位置的状态。如果您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;
        }
    }
于 2012-12-07T12:04:35.917 回答
0

最好在您的记录中添加一个标志,以指示它们是否已被检查。这意味着一个条目将有一个名称、一个数字和一个标志(选中/未选中)。

在您Adapter自己中,您可以检查此标志的值并采取相应的行动。

(一个相关的答案是关于这里ListView给出的复选框)

于 2012-12-06T15:50:30.103 回答