在Android平台中,CursorAdapter是一个适配器,用来把Cursor对象的数据展示到ListView控件里。RecyclerView适配器的第二篇将解释如何自己构造一个简单可重用的Cursor适配器,以及如何在你的应用中使用它。第三篇文章中,我将展示一个CursorAdapter类的更高级版本。
(相比于Android CursorAdapter,本例中用到的Cursor,不包含名为“_id”的列)
首先,我们创建一个抽象类RecyclerViewCursorAdapter,该类持有Cursor对象并实现一些RecyclerView.Adapter类需要的方法(例如getItemCount())。
而且,我们的适配器类将定义一个新的方法叫做onBindViewHolder(RecyclerView.ViewHolder, Cursor)。所以,你不需要每次获取Cursor对象来将数据绑定到ViewHolder。
我们还增加了一些帮助方法,例如:
- swapCursor(Cursor):提供带数据集(dataset)的适配器。
- getItem(int):获得Cursor对象,移动到正确的位置。
- getCursor():获得Cursor对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import android.database.Cursor; import android.support.v7.widget.RecyclerView; public abstract class RecyclerViewCursorAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { private Cursor cursor; public void swapCursor(final Cursor cursor) { this.cursor = cursor; this.notifyDataSetChanged(); } @Override public int getItemCount() { return this.cursor != null ? this.cursor.getCount() : 0; } public Cursor getItem(final int position) { if (this.cursor != null && !this.cursor.isClosed()) { this.cursor.moveToPosition(position); } return this.cursor; } public Cursor getCursor() { return this.cursor; } @Override public final void onBindViewHolder(final VH holder, final int position) { final Cursor cursor = this.getItem(position); this.onBindViewHolder(holder, cursor); } public abstract void onBindViewHolder(final VH holder, final Cursor cursor); } |
实现这个抽象类并填充数据是相当简单的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
import android.content.Context; import android.database.Cursor; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import butterknife.Bind; import butterknife.ButterKnife; public class SearchResultsCursorAdapter extends RecyclerViewCursorAdapter<SearchResultsCursorAdapter.SearchResultViewHolder> implements View.OnClickListener { private final LayoutInflater layoutInflater; private OnItemClickListener onItemClickListener; public SearchResultsCursorAdapter(final Context context) { super(); this.layoutInflater = LayoutInflater.from(context); } public void setOnItemClickListener(final OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } @Override public SearchResultViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { final View view = this.layoutInflater.inflate(R.layout.listitem_search, parent, false); view.setOnClickListener(this); return new SearchResultViewHolder(view); } @Override public void onBindViewHolder(final SearchResultViewHolder holder, final Cursor cursor) { holder.bindData(cursor); } /* * View.OnClickListener */ @Override public void onClick(final View view) { if (this.onItemClickListener != null) { final RecyclerView recyclerView = (RecyclerView) view.getParent(); final int position = recyclerView.getChildLayoutPosition(view); if (position != RecyclerView.NO_POSITION) { final Cursor cursor = this.getItem(position); this.onItemClickListener.onItemClicked(cursor); } } } public static class SearchResultViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.textview_name) TextView textViewName; public SearchResultViewHolder(final View itemView) { super(itemView); ButterKnife.bind(this, itemView); } public void bindData(final Cursor cursor) { final String name = cursor.getString(cursor.getColumnIndex("name")); this.textViewName.setText(name); } } public interface OnItemClickListener { void onItemClicked(Cursor cursor); } } |
Providing the adapter with data in your Activity / Fragment:
在Activity或Fragment中提供带数据的适配器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
import android.app.Activity; import android.app.LoaderManager; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; public class SearchActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> { private static final int LOADER_SEARCH_RESULTS = 1; private SearchResultsCursorAdapter adapter; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // create adapter this.adapter = new SearchResultsCursorAdapter(this); // start loader this.getLoaderManager().restartLoader(LOADER_SEARCH_RESULTS, null, this); } @Override public Loader<Cursor> onCreateLoader(final int id, final Bundle args) { switch (id) { case LOADER_SEARCH_RESULTS: final Uri uri = Uri.parse("content://some_uri"); return new CursorLoader(this, uri, null, null, null, null); } return null; } @Override public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) { switch (loader.getId()) { case LOADER_SEARCH_RESULTS: this.adapter.swapCursor(data); break; } } @Override public void onLoaderReset(final Loader<Cursor> loader) { switch (loader.getId()) { case LOADER_SEARCH_RESULTS: this.adapter.swapCursor(null); break; } } } |