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