1

電話の連絡先をListView(Cursoradapterを使用)として表示するAndroidアプリを開発しています。今、listViewにチェックボックスを追加したいのですが、チェックボックスのデータをデータベースに挿入する方法がチェックされているかどうかに基づいています。

私のデータベースクラスには、データベースに名前と番号を追加するために使用する関数があります。

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

CursorAdapterクラスでこの関数を呼び出す必要がありますか?

最近、getView関数を使うべきだと気づきましたが、残念ながらgetViewについてはわかりません。質問は

1-この関数をMyCursorAdapterまたはそれ以外で使用する必要がありますか?

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

2 に答える 2

3

まず、必要ありませんgetViewbindViewと組み合わせるとnewView、その代わりとして完全に十分ですが、おそらくもっと良いと言う人もいます。さらに、新しいビューで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());
                    }
                }
            });

内のオブジェクトのIDのようにカーソル位置を使用しましたHashMap。また、チェックボックスがオフになっていて、配置されたオブジェクトを削除したい場合は、使用した識別子を参照するだけです。より賢明な人は、削除する前にその位置に何かがあるかどうかを確認したいと思うかもしれません。それはあなたの裁量です。これでほぼ完了です。HashMapをデータベースのエントリに変換するにはどうすればよいですか?データベースオブジェクトにアクセスし、ループしてから、オブジェクトを1つずつ取得する必要があります。問題は今どこにあるかです。アダプターで直接行うこともできますが、私の場合、他のタスクのアクティビティ用にデータベースがすでに作成されており、自分よりも多くのオブジェクトを作成したくないため、通常はアクティビティでこのようなことを行います。にプッシュしました。したがって、私たちにできることは、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は、から渡されたIDを参照しHashMapます。挿入するたびに、最初にその前のIDが存在するかどうかを確認してから、何をしたいかを決定すると思いました。これは完璧な解決策ではありませんが、その問題が発生する可能性があることを警告し、それを管理するためのヒントを提供したいと思います。一般に、挿入メソッドは、数行だけを挿入する場合は問題ありませんが、挿入するものがたくさんある場合は、パフォーマンスのために一括トランザクションを調べたい場合があります。

もう1つ、リストビューのチェックボックスは、通常予想されるように状態が持続することを期待できません。チェックボックスが各位置でどのような状態になるかを明示的に指定する必要があります。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 に答える