20

Tôi có một số dữ liệu trong cơ sở dữ liệu SQLite. Tôi có một nhà cung cấp nội dung sẽ lấy dữ liệu từ cơ sở dữ liệu. Bây giờ vấn đề là làm thế nào để tôi thực hiện cursorLoader để làm việc trong tay với recyclerview?Recyclerview + Nhà cung cấp nội dung + CursorLoader

Ngoài ra, bất kỳ ai cũng có thể giải thích lý do tại sao chúng tôi cần truyền dữ liệu từ con trỏ đến đối tượng để hiển thị trong chế độ xem danh sách/recyclerview chứ không phải trực tiếp từ con trỏ?

Ví dụ, Trong lớp CursorAdapter tùy chỉnh,

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

HOẶC

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

Mà một trong những phương pháp trên là tốt hơn?

Trong quá khứ, chúng tôi từng có chế độ xem danh sách và chế độ xem lưới và có vẻ như giờ đây chúng được kết hợp để trở thành recyclerview. Sau đó, làm thế nào để tôi thực hiện một recyclerview dựa trên lưới?

+0

bạn không phải sử dụng bất kỳ danh sách nào: sử dụng ItemBridgeAdapter + CursorObjectAdapter hoặc liên kết trực tiếp với con trỏ trong RecyclerView.Adapter tùy chỉnh của bạn – pskink

+0

thành thật mà không biết tại sao CursorObjectAdapter nằm trong thư viện hỗ trợ "leanback" được thiết kế cho thiết bị TV nó phải là một phần của bất kỳ thư viện hỗ trợ "mục đích chung" nào – pskink

+0

@pskink Tôi phải giải quyết vấn đề này hiện nay. Bạn sẽ vui lòng cung cấp một ví dụ ngắn về cách tôi có thể 'ràng buộc con trỏ trực tiếp trong [my] tùy chỉnh RecyclerView.Adapter'? Điều đó sẽ rất hữu ích. Cảm ơn. Và hãy gắn thẻ tôi trong phần bình luận của câu trả lời khi bạn làm như vậy tôi biết. Cảm ơn vì bất kì sự giúp đỡ nào của bạn. –

Trả lời

4

Nói chung, bạn nên cố gắng tách biệt trách nhiệm xem và dữ liệu. Vì vậy, những gì bạn cần là để có được tất cả các đối tượng của bạn từ cơ sở dữ liệu trước sau đó thiết lập một Adaptor mà trông giống như sau:

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

Sau đó, bạn có thể gắn adapter vào RecyclerView bởi:

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

Để trả lời câu hỏi thứ hai của bạn ("Trong quá khứ, chúng tôi đã từng có chế độ xem danh sách và chế độ xem lưới và có vẻ như bây giờ chúng được kết hợp để trở thành recyclerview. Sau đó, làm cách nào để triển khai lưới dựa trên recyclerview?"):

Khi ràng buộc một LayoutManager cho RecyclerView bạn có thể quyết định một trong những bạn thực hiện:

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

hoặc

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

Có một số LayoutManagers. Tìm hiểu thêm here.

UPDATE: Bạn không cần phải tải tất cả các mục trước, chỉ cần đổi tên setItems để addItems và bạn tốt để đi

+1

Bạn nói: "Vì vậy, những gì bạn cần là lấy tất cả các đối tượng của bạn từ cơ sở dữ liệu trước", nhưng nếu tôi có 12.000 đối tượng để lấy từ cơ sở dữ liệu , và đây là lý do chính chọn cơ chế ContentProvider (để tải lười biếng cho tôi)? – miroslavign

+0

Làm cách nào để bạn giữ cho mảng được đồng bộ với cơ sở dữ liệu? – 0xcaff

3

Có một số Github GIST/dự án như thisthis mà hiển thị một ví dụ sử dụng trường hợp.

Mặc dù bạn sẽ sử dụng Bộ điều hợp được tùy chỉnh cho phù hợp với bộ điều hợp con trỏ, bạn sẽ sử dụng GridLayoutManager/LinearLayoutManager như bình thường.

1

Tôi nghĩ rằng bạn có thể sử dụng trực tiếp Tuỳ chỉnh CursorAdapter cho RecyclerView vì vậy bạn không cần phải chuyển đổi Cursor để 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); 
     } 
    } 
} 

Có thể nó sẽ hữu ích cho bạn.:)

Các vấn đề liên quan