20

我有一些SQLite数据库中的数据。我有一个内容提供者,它将从数据库中获取数据。现在问题是我如何实现cursorLoader与recyclerview一起工作?Recyclerview +内容提供商+光标加载器

另外,任何人都可以解释为什么我们需要将数据从光标传输到一个对象,以便在listview/recyclerview中显示而不是直接从光标显示?

例如,在自定义CursorAdapter类,

Person person = new Person(cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME))); 
textview.setText = person.getName(); 

OR

textview.setText = cursor.getString(cursor.getColumnIndexOrThrow(PERSON_NAME)); 

哪个的上述方法是更好的?

过去,我们曾经有过listview和gridview,看起来现在它们被组合起来成为recyclerview。那么,我如何实现基于网格的回收站?

+0

你不必使用任何列表:使用ItemBridgeAdapter + CursorObjectAdapter或直接绑定光标在你的自定义RecyclerView.Adapter – pskink

+0

老实说,我不知道为什么CursorObjectAdapter是在“leanback”支持库,它是专为电视设备,imho它应该是任何“通用”支持库的一部分 – pskink

+0

@pskink我现在不得不解决这个问题。请您提供一个简单的例子,说明如何在[我的]自定义RecyclerView.Adapter中直接绑定游标?这将非常有帮助。谢谢。当你这样做时,请在回复的评论中加上标签。感谢您的任何帮助,您可以提供。 –

回答

4

一般来说,您应该尝试将视图和数据职责分开。所以,你需要的是从数据库中获取预先所有的对象,然后设置一个适配器,它看起来像以下:

final CustomAdapter adapter = new CustomAdapter(); 
adapter.setItems(mPersons); 
mRecyclerView.setAdapter(); 

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

回答你的第二个问题(“过去,我们曾经有过listview和gridview,看起来它们现在合并成为recyclerview。那么,我该如何实现基于网格的recyclerview?”):

当绑定一个LayoutManager到RecyclerView你可以决定哪个一个你拿:

final LinearLayoutManager layoutManager = new LinearLayoutManager(this); 
mRecyclerView.setLayoutManager(layoutManager); 

final GridLayoutManager layoutManager = new GridLayoutManager(this, COLUMN_SPAN_COUNT); 
mRecyclerView.setLayoutManager(layoutManager); 

有几个布局管理。了解更多here

UPDATE: 您不必装载提前的所有项目,只需重命名setItems来为addItems,你是好去

+1

你说:“所以你需要的是事先从数据库中获取所有的对象”,但是如果我有12.000个对象从数据库中获取,这是选择ContentProvider机制的主要原因(为我做延迟加载)? – miroslavign

+0

你是如何保持阵列与数据库同步的? – 0xcaff

3

有喜欢thisthis几个Github上学家/项目,这表明这样的使用案件。

虽然您将使用为游标适配器定制的适配器,但您可以像往常一样使用GridLayoutManager/LinearLayoutManager。

1

我想你可以直接使用自定义CursorAdapterRecyclerView,所以你不必转换光标的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); 
     } 
    } 
} 

也许这将是对你有用。:)