Recyclerview + поставщик контента + CursorLoader
У меня есть некоторые данные в базе данных SQLite. У меня есть поставщик контента, который получит данные из базы данных. Теперь проблема в том, как я могу реализовать cursorLoader для работы с recyclerview?
Кроме того, кто-нибудь может объяснить, почему нам нужно перенести данные с курсора на объект, который будет отображаться в listview/recyclerview, а не прямо из курсора?
Например, в пользовательском классе cursorAdapter
Person person = new Person(cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME)));
textview.setText = person.getName();
ИЛИ
textview.setText = cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME));
Какой из вышеперечисленных методов лучше?
Раньше у нас было listview и gridview, и теперь кажется, что они объединены, чтобы стать recyclerview. Затем, как мне реализовать recyclerview на основе сетки?
Ответы
Ответ 1
В целом вы должны попытаться отделить требования к представлению и данным. Так что вам нужно получить все ваши объекты из базы данных заранее, а затем настроить адаптер, который выглядит следующим образом:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private final List<Person> objectList = new ArrayList<>();
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(layoutInflater.inflate(R.layout.adapter_item, parent, false));
}
@Override
public void onBindViewHolder(final CustomAdapter.ViewHolder holder, final int position) {
holder.bindItem(objectList.get(position));
}
// Set the persons for your adapter
public void setItems(final List<Person> persons) {
objectList.addAll(persons);
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return objectList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView mTextViewTitle;
private Object mObject;
public ViewHolder(final View itemView) {
super(itemView);
mTextViewTitle = (TextView) itemView.findViewById(R.id.view_item_textViewTitle);
mTextViewTitle.setText(mObject.getText());
}
private void bindItem(@NonNull final Person object) {
mObject = object;
}
}
}
Затем вы можете привязать адаптер к RecyclerView с помощью:
final CustomAdapter adapter = new CustomAdapter();
adapter.setItems(mPersons);
mRecyclerView.setAdapter();
Чтобы ответить на ваш второй вопрос ( "Раньше у нас были списки и gridview, и теперь кажется, что они объединены, чтобы стать recyclerview. Затем, как мне реализовать grid-recyclerview?" ):
При привязке LayoutManager к RecyclerView вы можете решить, какой из них вы берете:
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
или
final GridLayoutManager layoutManager = new GridLayoutManager(this, COLUMN_SPAN_COUNT);
mRecyclerView.setLayoutManager(layoutManager);
Существует несколько LayoutManagers. Подробнее здесь.
UPDATE:
Вам не нужно загружать все предметы заранее, просто переименуйте setItems в addItems, и вам хорошо идти
Ответ 2
Есть несколько Github gists/projects, таких как this и this, которые показывают такой прецедент.
В то время как вы будете использовать адаптор, специально адаптированный для адаптера курсора, для обычного использования вы должны использовать GridLayoutManager/LinearLayoutManager.
Ответ 3
Я думаю, вы можете использовать непосредственно Custom CursorAdapter
для RecyclerView
, поэтому вам не нужно преобразовывать Курсор в ArrayList
public class ProductListAdapter extends RecyclerView.Adapter<ProductListAdapter.ViewHolder> {
// Because RecyclerView.Adapter in its current form doesn't natively
// support cursors, we wrap a CursorAdapter that will do all the job
// for us.
CursorAdapter mCursorAdapter;
Activity mContext;
Random rnd;
public ProductListAdapter(AppCompatActivity context, Cursor c) {
mContext = context;
rnd = new Random();
mCursorAdapter = new CursorAdapter(mContext, c, 0) {
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// Inflate the view here
LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
return inflater.inflate(R.layout.row_product_layout_grid, parent, false);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String productName = cursor.getString(cursor.getColumnIndex(TProduct.PRODUCT_NAME));
// Binding operations
((TextView) view.findViewById(R.id.sub_product_name_text_view)).setText(productName);
int color = Color.argb(200, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
String url = "http://dummyimage.com/300/" + color + "/ffffff&text=" + (cursor.getPosition() + 1);
Picasso
.with(context)
.load(url)
.placeholder(R.mipmap.ic_launcher) // can also be a drawable
.into((ImageView) view.findViewById(R.id.sub_product_image_view));
}
};
}
public void reQuery(Cursor c) {
if (mCursorAdapter != null) {
mCursorAdapter.changeCursor(c);
mCursorAdapter.notifyDataSetChanged();
}
}
@Override
public int getItemCount() {
return mCursorAdapter.getCount();
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Passing the binding operation to cursor loader
mCursorAdapter.getCursor().moveToPosition(position); //EDITED: added this line as suggested in the comments below, thanks :)
mCursorAdapter.bindView(holder.view, mContext, mCursorAdapter.getCursor());
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Passing the inflater job to the cursor-adapter
View v = mCursorAdapter.newView(mContext, mCursorAdapter.getCursor(), parent);
return new ViewHolder(v);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
View view;
public ViewHolder(View itemView) {
super(itemView);
view = itemView.findViewById(R.id.product_row_card_view);
}
}
}
Пусть это будет полезно для вас.:)