2015-07-13 71 views
1

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

的CursorAdapter:

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

DatabaseProvider:

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 

回答

0

更多的挖掘后,我发现两个问题:

首先,onCheckChanged似乎至 总是被调用两次,这也许是一个android bug?请参阅下面的文章: 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(); 
     } 
    }); 
}