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

也許這將是對你有用。:)