由ViewPagerAdapter管理的片段实现了LoaderCallbacks。它查询数据库以获取Cursor,其中包含收藏字段的所有行等于1(true)。当用户在表更新中取消选择favorite-toggle_button favorite字段为0(false)时。我相信然后Loader调用onLoadFinished()来交换游标,因此列表视图应该在没有该特定项目的情况下进行更新。但这只发生在列表中的最后一项(最底部)。当我尝试删除最后一项时 - 它会立即移除并重新出现。我不明白它为什么会这样。
有什么想法?
public class SongsFavouriteFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
...
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_container_listview,container,false);
mAmdmAdapter = new AmdmAdapter(getActivity(), null, 0, R.layout.song_art_item);
ListView songsListView = (ListView)v.findViewById(R.id.container_listview);
songsListView.setAdapter(mAmdmAdapter);
songsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
...
}
});
return v;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
getLoaderManager().initLoader(LOADER_ID, null, this);
super.onActivityCreated(savedInstanceState);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri songsUri = AmdmContract.SongEntry.buildSongJoinArtistUri();
String[] projection = SONG_COLUMNS;
String selection = TABLE_NAME + "." + COLUMN_FAVORITE + " = 1 ";
return new CursorLoader(getActivity(),
songsUri,
projection,
selection,
null,
null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mAmdmAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
mAmdmAdapter.swapCursor(null);
}
}
和适配器
public class AmdmAdapter extends CursorAdapter {
public AmdmAdapter (Context context, Cursor c, int flags, int layout) {
super(context, c, flags);
this.layout = layout;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(layout, parent, false);
return view;
}
@Override
public void bindView(View view, Context context, final Cursor cursor) {
ViewHolder viewHolder = new ViewHolder(view);
...
if (viewHolder.toggle_song != null) { // here is my favourite toggle button
viewHolder.toggle_song.setChecked(cursor.getInt(COL_FAVOURITE) == 1);
viewHolder.toggle_song.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int favourite = isChecked ? 1 : 0;
ContentValues value = new ContentValues();
String where = AmdmContract.SongEntry.TABLE_NAME + "." +
AmdmContract.SongEntry._ID + " = " + tableId;
value.put(AmdmContract.SongEntry.COLUMN_FAVORITE, favourite);
mContext.getContentResolver()
.update(AmdmContract.SongEntry.CONTENT_URI,
value, where, null);
if (songName != null)
Log.d(DEBUG_TAG, "OnCheckedChanged: id = " + tableId + ", songName = " + songName +
", favourite = " + favourite);
}
}
});
}
}
@Override
public Cursor swapCursor(Cursor newCursor) {
if (newCursor != null) {
COl_ID = newCursor.getColumnIndex("_id");
COL_ARTIST_ID = newCursor.getColumnIndex("artist_id");
COL_ARTIST_NAME = newCursor.getColumnIndex("artist_name");
COL_SONG_NAME = newCursor.getColumnIndex("song_name");
COL_DATE_ADD = newCursor.getColumnIndex("date_add");
COL_FAVOURITE = newCursor.getColumnIndex("favourite");
COL_PHOTO = newCursor.getColumnIndex("photo");
}
return super.swapCursor(newCursor);
}
...
}
更新:
@Override
public int update(
Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int rowsUpdated;
switch (sUriMatcher.match(uri)) {
...
case SONGS: {
rowsUpdated = db.update(AmdmContract.SongEntry.TABLE_NAME,
values, selection, selectionArgs);
break;
}
...
default:
throw new UnsupportedOperationException("Unknown uri: " +
uri);
}
if (rowsUpdated != 0)
getContext().getContentResolver().notifyChange(uri, null);
Log.d(LOG_TAG,"update(): " + rowsUpdated + " rows updated");
return rowsUpdated;
}
答案 0 :(得分:0)
假设您更新数据库的查询是正确的,那么您错过了将所有内容放在一起的难题。 ContentResolver
与LoaderManager
/ CursorLoader
没有直接关联。 getContentResolver().update
不会导致LoaderMananger重新启动并再次查询数据库。您需要注册一个ContentObserver
来监听更新表后通知的Uri
上的更改。调用onChange
时,您必须重新启动LoaderManager
答案 1 :(得分:0)
我的错误是在setOnCheckedChangeListener()之前放置setChecked()。
列表重用项目,因此当光标更新时,旧项目将填充新数据。 setChecked()调用切换按钮,它导致调用已注册已从游标行中删除的onCheckedChangeListener。
当我在setChecked()之前放入setOnCheckedChangeListener()时,一切都按预期工作。 希望它会帮助别人。