我尝试新的DiffUtil
来获取RecyclerView.Adapter
中的差异。但是重新加载的旧光标在可以计算差异之前关闭,我不知道为什么。此CursorCallback
是Callback
基础,此Adapter
是我的基础,这是我的活动代码:
public class RecyclerActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private RecyclerView recyclerView;
private ItemAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize( true );
recyclerView.setLayoutManager(new LinearLayoutManager(this) );
recyclerView.setAdapter(adapter = new ItemAdapter(this));
recyclerView.setItemAnimator(new ItemAnimator());
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
long id = recyclerView.getAdapter().getItemId( viewHolder.getAdapterPosition() );
viewHolder.itemView.getContext().getContentResolver().delete(ContentUris.withAppendedId(CategoryContract.CONTENT_URI, id), null, null);
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
getSupportLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(this, CategoryContract.CONTENT_URI, CategoryContract.PROJECTION, null, null, CategoryContract.COLUMN_ID + " DESC");
}
public void addItem( View button ) {
int count = recyclerView != null ? recyclerView.getChildCount() : 0;
ContentValues v = new ContentValues(1);
v.put(CategoryContract.COLUMN_NAME, "Foo Nr. " + count);
getContentResolver().insert(CategoryContract.CONTENT_URI, v);
}
private Task setter;
@Override
public void onLoadFinished( final Loader<Cursor> loader, final Cursor data) {
if( setter != null) {
setter.cancel(true);
}
setter = new Task( adapter );
AsyncTaskCompat.executeParallel(setter, adapter.getCursor(), data );
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.changeCursor(null);
}
public static class Task extends AsyncTask<Cursor, Void, Pair<Cursor, DiffUtil.DiffResult>> {
private final CursorRecyclerViewAdapter adapter;
Task(CursorRecyclerViewAdapter adapter) {
this.adapter = adapter;
}
@Override
protected Pair<Cursor, DiffUtil.DiffResult> doInBackground(Cursor... params) {
return Pair.create( params[1], DiffUtil.calculateDiff( new ItemCallback( params[0], params[1]) ) );
}
@Override
protected void onPostExecute(Pair<Cursor, DiffUtil.DiffResult> diffResult) {
if( isCancelled() )
return;
adapter.swapCursor(diffResult.first);
diffResult.second.dispatchUpdatesTo(adapter);
}
}
public static class ItemAdapter extends CursorRecyclerViewAdapter<ItemHolder>
{
ItemAdapter( Context context ) {
super(context, null);
}
@Override
public void onBindViewHolder(ItemHolder viewHolder, Cursor cursor) {
CategoryModel model = CategoryModel.FACTORY.createFromCursor( cursor );
viewHolder.textView.setText( model.getId() + " - " + model.getName() );
}
@Override
public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemHolder(LayoutInflater.from( parent.getContext() ).inflate( R.layout.item, parent, false ));
}
}
public static class ItemHolder extends RecyclerView.ViewHolder {
TextView textView;
ItemHolder(View itemView) {
super(itemView);
textView = ( TextView ) itemView.findViewById(R.id.textView);
}
}
public static class ItemCallback extends CursorCallback<Cursor> {
public ItemCallback(Cursor newCursor, Cursor oldCursor) {
super(newCursor, oldCursor);
}
@Override
public boolean areRowContentsTheSame(Cursor oldCursor, Cursor newCursor) {
CategoryModel oldCategory = CategoryModel.FACTORY.createFromCursor(oldCursor);
CategoryModel newCategory = CategoryModel.FACTORY.createFromCursor(newCursor);
return oldCategory.getName().equals( newCategory.getName() );
}
@Override
public boolean areCursorRowsTheSame(Cursor oldCursor, Cursor newCursor) {
return oldCursor.getLong(0) == newCursor.getLong(0);
}
}
}
欢迎任何帮助。当返回具有相同查询的新游标时,可能会关闭旧游标。我在getCursor()
中呼叫onLoadFinished()
但在首次使用时在CursorCallback
内关闭时,光标处于打开状态。
答案 0 :(得分:2)
您遇到了CursorLoader
的预期行为 - 无论您当前是否使用它,它们会在另一个光标到达后关闭旧光标。
您案例中的事件序列如下:
ContentResolver.notifyChanged
为了继续使用后台线程中的Cursor,你必须手动管理你的Cursor(没有CursorLoader的帮助):如果发生配置更改或onDestroy,你自己关闭它。
或者,只是截取异常并将其视为您的背景差异计算被取消的标志(无论如何不久将对另一个Cursor执行)。