在Android平台中,CursorAdapter[3]是一个适配器,用来把Cursor[4]对象的数据展示到ListView控件里。RecyclerView[5]适配器的第二篇将解释如何自己构造一个简单可重用的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对象。
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
public abstract class RecyclerViewCursorAdapter
extends RecyclerView.Adapter
{
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);
}
实现这个抽象类并填充数据是相当简单的。
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
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中提供带数据的适配器:
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
{
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 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 loader, final Cursor data)
{
switch (loader.getId())
{
case LOADER_SEARCH_RESULTS:
this.adapter.swapCursor(data);
break;
}
}
@Override
public void onLoaderReset(final Loader loader)
{
switch (loader.getId())
{
case LOADER_SEARCH_RESULTS:
this.adapter.swapCursor(null);
break;
}
}
}

1 赞