我在Android应用程序中使用ActiveAndroid ORM和UltimateRecyclerView。我不知道如何使用这个流行的库在列表中显示数据。我知道,数据正确保存到数据库。使用以下方法,我得到一个光标到我想要显示的数据。
public Cursor eventsCursor() {
// `Event` is an ActiveAndroid model class
String query = new Select()
.from(Event.class)
.orderBy("time")
.toSql();
return ActiveAndroid.getDatabase().rawQuery(query, null);
}
我编写了与UltimateViewAdapter兼容的RecyclerView.Adapter<VH>
实现(EventCursorRecyclerAdapter
),它包含一个CursorAdapter成员以便使用数据库(代码基于this solution)。 ActiveAndroid(issue #3)中没有ContentObservers,因此我在初始化期间在ContentProvider上注册了一个观察者。初始化如下:
片段类
protected UltimateRecyclerView listView;
private AbstractCursorRecyclerAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
cursor = eventsCursor();
cursor.setNotificationUri(getActivity().getContentResolver(),
ContentProvider.createUri(Event.class, null));
adapter = new EventCursorRecyclerAdapter(getActivity(), cursor, R.layout.list_item_event);
getActivity().getSupportLoaderManager().initLoader(0, savedInstanceState, this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/* ... */
// Configure RecyclerView
listView.setLayoutManager(new LinearLayoutManager(getActivity()));
listView.setAdapter(adapter);
}
我使用ActiveAndroid的ContentProvider(docs)为CursorLoader创建URI:
的AndroidManifest.xml
<application ...>
<provider
android:name="com.activeandroid.content.ContentProvider"
android:authorities="com.activeandroid.content.ContentProvider"
android:exported="false" />
...
</application>
LoaderManager.LoaderCallbacks<T>
实施
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle cursor) {
return new CursorLoader(
MyFragment.this.getActivity(),
ContentProvider.createUri(Event.class, null),
null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.asCursorAdapter().changeCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.asCursorAdapter().changeCursor(null);
}
当我检测到数据集中的更改时,我调用
MyFragment.this.getActivity().getContentResolver().notifyChange(
ContentProvider.createUri(Event.class, modifiedId), null);
我不知道为什么,但它不起作用。没有数据显示,没有记录错误。
更新适配器的完整代码(提醒matryoshka)。
EventCursorAdapter
public class EventCursorAdapter extends CursorAdapter {
private final int itemLayoutId;
private final LayoutInflater inflater;
/**
* @param itemLayoutId List item layout
*/
public EventCursorAdapter(Context context, Cursor cursor, @LayoutRes int itemLayoutId) {
super(context, cursor, 0);
this.itemLayoutId = itemLayoutId;
this.inflater = LayoutInflater.from(context);
}
/**
* It is used to inflate a new view and return it.
*
* @return a new View
*/
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return inflater.inflate(itemLayoutId, parent, false);
}
/**
* Bind all data to a given view (such as setting the text on a TextView).
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
EventItemViewHolder holder = (EventItemViewHolder) view.getTag();
// Extract properties and populate fields
holder.tvName.setText(cursor.getString(holder.nameIndex));
/* ... */
}
}
EventCursorRecyclerAdapter
public final class EventCursorRecyclerAdapter extends AbstractCursorRecyclerAdapter {
/**
* @param itemLayoutId List item layout
*/
public EventCursorRecyclerAdapter(Context context, Cursor cursor, @LayoutRes int itemLayoutId) {
super(new EventCursorAdapter(context, cursor, itemLayoutId), context);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
cursorAdapter.bindView(holder.itemView, context, cursorAdapter.getCursor());
}
@Override
public UltimateRecyclerviewViewHolder onCreateViewHolder(ViewGroup parent) {
// Passing the inflater job to the cursor-adapter
View v = cursorAdapter.newView(context, cursorAdapter.getCursor(), parent);
return new EventItemViewHolder(v, cursorAdapter.getCursor());
}
/**
* See ViewHolder Pattern.
*/
public final class EventItemViewHolder extends UltimateRecyclerviewViewHolder {
// Column indices
int nameIndex, timeIndex /*, ...*/;
// Views
TextView tvName, tvTime;
/* ... */
public EventItemViewHolder(View view, Cursor cursor) {
super(view);
// Find fields to populate in inflated template
tvName = (TextView) view.findViewById(R.id.tv_event_name);
tvTime = (TextView) view.findViewById(R.id.tv_event_time);
/* ... */
// Find columns
nameIndex = cursor.getColumnIndexOrThrow("name");
timeIndex = cursor.getColumnIndexOrThrow("time");
}
}
}
AbstractCursorRecyclerAdapter
public abstract class AbstractCursorRecyclerAdapter extends UltimateViewAdapter {
// PATCH: Because RecyclerView.Adapter in its current form doesn't natively support cursors,
// we "wrap" a CursorAdapter that will do all teh job for us
protected final CursorAdapter cursorAdapter;
protected final Context context;
public AbstractCursorRecyclerAdapter(CursorAdapter cursorAdapter, Context context) {
setHasStableIds(true);
this.cursorAdapter = cursorAdapter;
this.context = context;
}
@Override
public int getAdapterItemCount() {
return cursorAdapter.getCount();
}
@Override
public long getItemId(int position) {
return cursorAdapter.getItemId(position);
}
private Model getItem(int position) {
return (Model) cursorAdapter.getItem(position);
}
public CursorAdapter asCursorAdapter() {
return cursorAdapter;
}
public void remove(int position) {
Model entity = getItem(position);
if (entity != null) {
entity.delete();
notifyDataSetChanged();
}
}
}
Gradle依赖
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
compile 'com.marshalchen.ultimaterecyclerview:library:0.3.2'