Android 由于回收,行背景发生变化。getView()实现不需要';我不能解决这个问题

Android 由于回收,行背景发生变化。getView()实现不需要';我不能解决这个问题,android,android-listview,android-cursoradapter,Android,Android Listview,Android Cursoradapter,我一直在stack上寻找很多指南、教程和答案,但我还是弄不清这一个 我有一个自定义的可绘制状态。如果我单击列表视图中的一行,它将突出显示并更新数据库中的此信息。(一项任务(习惯)已经完成)。在我开始滚动之前,一切都很好。我了解到,需要用getViewTypeCount()覆盖getView()方法,也可能覆盖getItemViewType() 如何正确地做到这一点?我的HabitCursorAdapter代码与getView()和其他提到的方法目前看起来是这样的 public class Hab

我一直在stack上寻找很多指南、教程和答案,但我还是弄不清这一个

我有一个自定义的可绘制状态。如果我单击
列表视图中的一行,它将突出显示并更新数据库中的此信息。(一项任务(习惯)已经完成)。在我开始滚动之前,一切都很好。我了解到,需要用
getViewTypeCount()
覆盖
getView()
方法,也可能覆盖
getItemViewType()

如何正确地做到这一点?我的HabitCursorAdapter代码与getView()和其他提到的方法目前看起来是这样的

public class HabitsCursorAdapter extends CursorAdapter {

    private LayoutInflater inflater;
    private Context context;

public static final int PERFORMED = 1;
public static final int NOT_PERFORMED = 0;

    public HabitsCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
        inflater = LayoutInflater.from(context);
        this.context = context;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        String habitName = cursor.getString(cursor
                .getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_NAME));
        TextView habitNameTV = (TextView) view.findViewById(R.id.habit_name);
        habitNameTV.setText(habitName);


        /*******************   OK   ***********************/
        ImageButton editButton = (ImageButton) view.findViewById(R.id.habit_edit_button);
        Integer _id = cursor.getInt(cursor.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_ID));
        editButton.setTag(R.id.EDITED_HABIT_ID, _id);
        view.setTag(_id);

        editButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent i = new Intent(HabitsCursorAdapter.this.context,
                        HabitDetailActivity.class);
                i.putExtra("_id", (Integer) v.getTag(R.id.EDITED_HABIT_ID));
                HabitsCursorAdapter.this.context.startActivity(i);
            }
        });

        ImageButton deleteButton = (ImageButton) view
                .findViewById(R.id.habit_history_button); // NEED TO REWRITE TO DELETING BUTTON
        deleteButton.setTag(R.id.EDITED_HABIT_ID, _id);
        deleteButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                //itemized due debugging issue
                HabitListActivity hla = ((HabitListActivity) HabitsCursorAdapter.this.context);
                Object o = v.getTag(R.id.EDITED_HABIT_ID);
                Integer i = (Integer) o;
                long l = i.longValue();
                hla.delete(l);
            }
        });
        /*******************   OK   **********************/

        HabitListItemView hv = (HabitListItemView) view;
        hv.setHabitPerformed(
                (1 == cursor.getInt(cursor.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED))) ? true : false
                    );
        view.refreshDrawableState();
    }

    @Override
    public View newView(Context context, Cursor c, ViewGroup container) {
        HabitListItemView v = (HabitListItemView) inflater.inflate(
                R.layout.habit_item_layout, container, false);
        bindView(v, context, c);        
        return v;
    }

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {

        Cursor c = (Cursor) getItem(position);

        c.moveToPosition(position);
        int value = c.getInt(c.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED));
        if(0 != value){
            return PERFORMED;
        }
        return NOT_PERFORMED;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (!mDataValid) {
            throw new IllegalStateException("this should only be called when the cursor is valid");
        }
        if (!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("couldn't move cursor to position " + position);
        }
        View v;
        if (convertView == null) {
            v = newView(mContext, mCursor, parent);
            return v;
        } else {

            mCursor.moveToPosition(position);

            HabitListItemView hv = (HabitListItemView) convertView;
            int convertViewIsPerformed = hv.getHabitPerformed() ? 1 : 0;
            int actualItemPerformed = getItemViewType(position); 

            if(actualItemPerformed == convertViewIsPerformed){              
                v = convertView;
                bindView(v, mContext, mCursor);
                return v;
            }else{
                v = newView(mContext, mCursor, parent);
                return v;
            }                       
        }
    }
}
自定义行视图为:

public class HabitListItemView extends RelativeLayout {

    private static final int[] STATE_HABIT_PERFORMED = { R.attr.state_habit_performed };

    private boolean performed;

    public HabitListItemView(Context context) {
        this(context, null);
    }

    public HabitListItemView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        loadViews();
    }

    public HabitListItemView(Context context, AttributeSet attributeSet,
            int defStyle) {
        super(context, attributeSet, defStyle);

        loadViews();
    }

    private void loadViews() {

        setBackgroundResource(R.drawable.habit_list_item_background);   

    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {

        if (performed) {

            final int[] drawableState = super
                    .onCreateDrawableState(extraSpace + 1);

            mergeDrawableStates(drawableState, STATE_HABIT_PERFORMED);

            return drawableState;
        } else {
            return super.onCreateDrawableState(extraSpace);
        }
    }

    public void setHabitPerformed(boolean performed) {
        this.performed = performed;
        refreshDrawableState();
}

public boolean getHabitPerformed() {
    return performed;
}

}
以及ListFragment中的
onListItemClick()

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        super.onListItemClick(l, v, position, id);

        HabitListItemView hv = (HabitListItemView) v;

        ContentValues cv = new ContentValues();



        String habitId = v.getTag().toString(); 
        SQLiteDatabase db = dh.getWritableDatabase();
        Cursor cPerfomed = db.query(SQLiteHabitHelper.TABLE_HABIT, 
                new String[]{SQLiteHabitHelper.COLUMN_ID, SQLiteHabitHelper.COLUMN_PERFORMED}, 
                "_id = ?", new String[]{habitId}, null, null, null);
        cPerfomed.moveToFirst();

        int performed = cPerfomed.getInt(cPerfomed.getColumnIndexOrThrow(SQLiteHabitHelper.COLUMN_PERFORMED));
        cPerfomed.close();

        cv.put(SQLiteHabitHelper.COLUMN_ID, (Integer) v.getTag());
        cv.put(SQLiteHabitHelper.COLUMN_PERFORMED, (performed == 0) ? 1 : 0);

        db.update(SQLiteHabitHelper.TABLE_HABIT, cv, "_id = ?", new String[]{habitId});
        db.close();
        hv.setHabitPerformed((performed == 0) ? true : false);


    }
一个关于如何以及何时调用重写方法的详细解释可能会帮助我解决这个问题。我假设newView和bindView只由getView调用,因此我相信我可以通过覆盖的getView来控制它。但是,getItemViewType和getViewTypeCount是由我没有实现的方法调用的,我不理解为什么以及如何使用结果。也许是他们造成了问题

如果需要更多的代码,我会根据需要编辑我的帖子


任何帮助都将不胜感激

我的一个朋友帮我发了这个链接

我尝试了这个解决方案,但是,我没有使用复选框,而是使用背景色

我必须相应地修改getView()方法:

public View getView(int position, View inView, ViewGroup parent) {
    if (inView == null) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inView = inflater.inflate(R.layout.habit_item_layout, null);
    }

    HabitListItemView hliv = (HabitListItemView) inView;

        mCursor.moveToPosition(position);
    bindView(hliv, mContext, mCursor);
    hliv.setHabitPerformed(habitPerformed.get(position)); //line added

    return inView;
}
并在适配器中添加一个数组,我将在其中存储,如果它的背景是否为绿色

public ArrayList<Boolean> habitPerformed = new ArrayList<Boolean>();

这就解决了我的问题。

你必须缩小你的问题范围。具体来说,什么东西没有按你想要的方式工作?是否尝试根据列表项是否已完成来更改该项中的视图?这是不相关的,但是您应该从UI线程中获取db查询。使用加载程序或异步任务。会让你很容易。你好,谢谢你有兴趣帮忙。刚才我有一个朋友帮我解答(见下文)。我已经在我的项目中使用了LoaderEx。但是,我不确定如何使用加载程序通过它执行更新查询。我猜它甚至不应该用于这类任务?因此,我可能应该使用AsyncTask。我说得对吗?
    if (hv.getHabitPerformed()) {
        adapter.habitPerformed.set(position, true);
    } else if (!hv.getHabitPerformed()) {
        adapter.habitPerformed.set(position, false);
    }