2

私は単純なタスク リスト アプリを作成しており、データベースを使用してすべてを保持しています。データを処理するために、ResourceCursorAdapter を拡張するカスタム CursorAdapter を作成しました。すべてが正常に表示されますが、それを超えると、大雑把になります。まず、私の実装:

import android.app.AlertDialog;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.ResourceCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Filterable;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * @author Dave Smith
 *
 */
public class TaskCursorAdapter extends ResourceCursorAdapter {

    /**
     * @param context
     * @param layout
     * @param c
     * @param from
     * @param to
     * @param flags
     */
    private Context context;
    private int layout, isCheckedFromDb, IdFromDb;
    private Cursor cursor;

    public TaskCursorAdapter(Context context, int layout, Cursor c,
            int flags) {
        super(context, layout, c, flags);
        this.context = context;
        this.layout = layout;
    }
    public TaskCursorAdapter(Context context, int layout){
        super(context, layout, null, 0);
        this.context = context;
        this.layout = layout;
    }
    public TaskCursorAdapter(Context context, int layout, Cursor c){
        super(context, layout, c, 0);
        this.context = context;
        this.layout = layout;
    }
    public TaskCursorAdapter(Context context, int layout, Cursor cursor, boolean autoRequery)
    {
        super(context, layout, cursor, autoRequery);
        this.context = context;
        this.layout = layout;
    }
    public View newView(Context context, Cursor cursor, ViewGroup parent){
        final LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(layout, parent, false);
        return v;
    }
    public void bindView(View v, Context context, Cursor c){
        CheckBox taskCheckBox = (CheckBox)v.findViewById(R.id.taskCheckBox);
        TextView taskText = (TextView)v.findViewById(R.id.taskTitle);
        TextView taskNote = (TextView)v.findViewById(R.id.taskNote);
        final long assignedID = v.getID();
        //v.setClickable(true);     
        //LinearLayout holder = (LinearLayout)v.findViewById(R.id.container);
        //holder.setClickable(true);
        //IdFromDb = c.getInt(c.getColumnIndex(NagTasksDatabaseHelper.ID));
        taskText.setText(c.getString(c.getColumnIndex(NagTasksDatabaseHelper.TASK)));
        taskNote.setText(c.getString(c.getColumnIndex(NagTasksDatabaseHelper.NOTE)));
        //isCheckedFromDb = c.getInt(c.getColumnIndex(NagTasksDatabaseHelper.CHECKED));
        taskCheckBox.setChecked(c.getInt(c.getColumnIndex(NagTasksDatabaseHelper.CHECKED))==1);
        //cursor = c;
        taskCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                //Really Old method:
                /*NagTasksDatabaseHelper helper = new NagTasksDatabaseHelper(null);
                int idCol = cursor.getColumnIndex(NagTasksDatabaseHelper.ID); 
                int taskID = helper.getNewTaskId();
                if (idCol!=-1)
                {
                    taskID= cursor.getInt(idCol);
                    if (isChecked){
                        helper.checkOffTask(taskID);
                    } else {
                        helper.uncheckTask(taskID);
                    }
                }
                //TODO Solve how to use helper to change ISCHECKED in database
                helper.close();
                //Old method:
                NagTasksDatabaseHelper helper = new NagTasksDatabaseHelper(null);
                if (isChecked) {
                    helper.checkOffTask(IdFromDb);
                } else {
                    helper.uncheckTask(IdFromDb);
                }
                helper.close();*/
                //Current method:

                if (assignedID!=View.NO_ID) {
                    NagTasksDatabaseHelper helper = new NagTasksDatabaseHelper(buttonView.getContext());
                    if (isChecked) {
                        helper.checkOffTask(assignedID);
                    } else {
                        helper.uncheckTask(assignedID);
                    }
                    helper.close();
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(buttonView.getContext());
                    builder.setMessage("No ID found. Try something else.");
                    builder.setCancelable(true);
                    builder.create().show();
                }
            } 
        });
    }

}

問題1

EDIT:方法はわかりませんが、問題は解決されました。

現在の状態では、実行すると Eclipse のコンソールにエラーが表示されます。動作にはまったく影響しませんが、CheckBox のみを持ち、CheckBox のテキストを変更しただけのレイアウトを使用した以前の実装では、このエラーは表示されませんでした。

[2012-06-18 16:10:15 - ddms] null
java.lang.NullPointerException
    at com.android.ddmlib.JdwpPacket.writeAndConsume(JdwpPacket.java:213)
    at com.android.ddmlib.Client.sendAndConsume(Client.java:575)
    at com.android.ddmlib.HandleHello.sendHELO(HandleHello.java:142)
    at com.android.ddmlib.HandleHello.sendHelloCommands(HandleHello.java:65)
    at com.android.ddmlib.Client.getJdwpPacket(Client.java:672)
    at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:317)
    at com.android.ddmlib.MonitorThread.run(MonitorThread.java:263)

[2012-06-18 16:10:15 - ddms] null
java.lang.NullPointerException
    at com.android.ddmlib.JdwpPacket.writeAndConsume(JdwpPacket.java:213)
    at com.android.ddmlib.Client.sendAndConsume(Client.java:575)
    at com.android.ddmlib.HandleHello.sendHELO(HandleHello.java:142)
    at com.android.ddmlib.HandleHello.sendHelloCommands(HandleHello.java:65)
    at com.android.ddmlib.Client.getJdwpPacket(Client.java:672)
    at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:317)
    at com.android.ddmlib.MonitorThread.run(MonitorThread.java:263)

問題2

この CursorAdapter を使用している ListFragment は、そのOnListItemClick()メソッドを実行していません。同様に、ListFragment の ListView を ContextMenu を使用するように登録しましたが ( を使用registerForContextMenu())、長押ししてもコンテキスト メニューが表示されません。

問題 3

一般に、コメントtaskCheckBox.setOnCheckedChangeListenerを外すと、checkBox がチェックされているときに悪いことが起こります。通常、何_idを呼び出すcheckOffTask()かまたはuncheckTask(). (編集:最新の編集で行われた変更...まだやりたいことを実行していませんが、少なくともクラッシュしません。またgetItemId()、位置を要求するのが面倒で、方法がわかりませんカーソルから ListView 内の特定のアイテムを取得するか、それを使用します。)


これらの問題を解決するのを手伝ってくれる人はいますか? 以前にこの件について助けを求めたにもかかわらず、CursorAdapters がどのように機能するかについては、まだほとんど不明です。

編集:私のアプリには、非常に軽く調整された別のリストがありResourceCursorAdapter(リンクされた質問を参照)、これらの問題はどれもそこにポップアップしていないことに注意してください。(ただし、問題 3 は文字列の単純なリストであるため、ポップアップする理由はありません。)

4

2 に答える 2

2

問題 1:

解決済みなので飛ばします。

問題 2:

この前の質問で述べたように、ビューにフォーカス可能なオブジェクトがある場合、SDK のバグにより、ビュー全体をクリック可能にすることはできません。そこで、膨張した XML を調べて、android:focusable="false"各項目に属性を追加しました。リスト アイテムがクリック可能になり、ロングクリック可能になりました。

問題 3:

reddit の素敵な仲間が指摘したように、私は「古い方法」で正しい軌道に乗っていましたfinal longが、パラメーターの代わりにローカルを使用する必要がありました。

于 2012-06-26T23:01:17.583 に答える
1

最初にランダムな提案。getColumnIndex を使用しないでください。少なくともどこかにキャッシュしてください。インデックスは常に射影の順序と一致するため、一般的なパターンはそれを使用することです (したがって、射影が ['_id', 'something', 'else'] の場合は、INDX_ID = 0; INDX_SOMETHING = 1; などを宣言します. ..)

したがって、そのような匿名の内部クラスを作成することは、実行できる最もパフォーマンスの高いことではありません。代わりに次のことを行います。

bindView の行 ID または位置でビューにタグを付けます (reddit に記載されているように、これはv.getID() ではありません)。これは、checkBoxView.setTag() を使用して行うことができます。これにより、データを任意にビューにタグ付けすることができます。

次に、チェック変更リスナーを新しいビューに登録します。理想的には、匿名のインナーの代わりに静的クラスを渡しますが、少なくとも newView で行うことで、それらを作成する頻度を制限します。コールバックは v.getTag() を使用して行 ID (または bindView に入力したもの) を取得し、それを使用して必要な作業を行うことができます。

于 2012-06-28T04:32:10.563 に答える