【问题标题】:Android - Why would Switch button on CursorAdaptor reset button immediately after a changeAndroid - 为什么会在更改后立即在 CursorAdaptor 重置按钮上切换按钮
【发布时间】:2015-07-14 20:52:05
【问题描述】:

我正在尝试基于 Switch 更新数据库表中的布尔值。 ListView 包含一个语言列表,每个语言都有一个“安装”切换按钮。我的 CursorAdapter 正在显示列表和开关。我为每个 Switch 设置了 OnCheckedChangeListeners。当我选择其中一个开关时,它会短暂显示它已打开,但会立即恢复为“关闭”。在我的日志记录中,我看到该值设置为“true”,并将其发送到 DatabaseProvider 以更新数据库。但紧接着,我看到另一个日志输出,该值为 false,然后在另一个更新中将其发送到 DatabaseProvider。

光标适配器:

public static class ViewHolder {
    public final TextView nameView;
    public final Switch installSwitch;

    public ViewHolder(View view) {
        nameView = (TextView) view.findViewById(R.id.language_textview);
        installSwitch = (Switch) view.findViewById(R.id.installed_switch);
    }
}

public LanguageAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    View view = LayoutInflater.from(context).inflate(R.layout.list_item_language, parent, false);
    ViewHolder viewHolder = new ViewHolder(view);
    view.setTag(viewHolder);
    return view;
}

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

    ViewHolder viewHolder = (ViewHolder) view.getTag();
    long languageId = cursor.getLong(0);
    String word = cursor.getString(1);
    boolean langInstalled = Boolean.parseBoolean(cursor.getString(2));
    viewHolder.nameView.setText(word);
    viewHolder.installSwitch.setChecked(langInstalled);
    viewHolder.installSwitch.setTag(languageId);

    viewHolder.installSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            long languageId = (long) buttonView.getTag();
            ContentValues cv = new ContentValues();
            cv.put(TranslationContract.LanguageEntry.COLUMN_INSTALLED, isChecked);
            Log.d(LOG_TAG, "onChecked, langID: " + languageId + " isChecked: " + isChecked);
            buttonView.getContext().getContentResolver().update(TranslationContract.LanguageEntry.CONTENT_URI, cv, TranslationContract.LanguageEntry._ID+"=?", new String[] {String.valueOf(languageId)});
       }
    });
}

数据库提供者:

public int update(
        Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    final int match = sUriMatcher.match(uri);
    int rowsUpdated;

    switch (match) {
        case LANGUAGES:
            rowsUpdated = db.update(LanguageEntry.TABLE_NAME, values, selection,
                    selectionArgs);
            Log.d(LOG_TAG, "Updating languages: " + values.toString());
            break;
 }

日志:

07-13 21:39:32.785    LanguageAdapter﹕ onChecked, langID: 2 isChecked: true
07-13 21:39:32.800    DatabaseProvider﹕ Updating languages: installed=true
07-13 21:39:32.813    LanguageAdapter﹕ onChecked, langID: 2 isChecked: false
07-13 21:39:32.825    DatabaseProvider﹕ Updating languages: installed=false

【问题讨论】:

    标签: android android-cursoradapter


    【解决方案1】:

    经过更多挖掘,我发现了两个问题:

    首先,onCheckChanged 似乎总是被调用两次,这可能是一个 android 错误?请参阅以下帖子: onCheckedChanged fired multiple times, Listview with checkboxCheckBox changes value twice

    改为使用 onClickListener。

    这里的第二个问题是 DB 游标和 java 代码之间的布尔值处理不正确。 SQLite 没有本机 BOOLEAN 类型,因此值作为整数 0 或 1 存储和返回。它们需要进行评估,然后转换为 java 布尔值。

    更正后的代码是:

    @Override
    public void bindView(View view, Context context, final Cursor cursor) {
    
        ViewHolder viewHolder = (ViewHolder) view.getTag();
        long languageId = cursor.getLong(0);
        String word = cursor.getString(1);
        boolean langInstalled = cursor.getInt(2)>0; //convert DB 1 or 0 to java boolean
        viewHolder.nameView.setText(word);
        viewHolder.installSwitch.setChecked(langInstalled);
        viewHolder.installSwitch.setTag(languageId);
        viewHolder.installSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CompoundButton button = (CompoundButton) v;
                long languageId = (long) button.getTag();
                boolean isChecked = button.isChecked();
                int dbBoolean = 0;
                if (button.isChecked()) {
                    dbBoolean = 1;
                }
                ContentValues cv = new ContentValues();
                cv.put(TranslationContract.LanguageEntry.COLUMN_INSTALLED, dbBoolean);
                button.getContext().getContentResolver().update(TranslationContract.LanguageEntry.CONTENT_URI, cv, TranslationContract.LanguageEntry._ID + "=?", new String[]{String.valueOf(languageId)});
                notifyDataSetChanged();
            }
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 2019-03-22
      • 2012-06-04
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 2016-10-16
      相关资源
      最近更新 更多