Tôi vừa gặp phải tình huống sau. Tôi có một ứng dụng Android với một kịch bản mà tôi đoán có thể xảy ra trong nhiều ứng dụng. Đó là về gắn thẻ/ghi nhãn/phân loại, gọi nó như bạn muốn. Về cơ bản tôi có các mối quan hệ sau trong SQLite DBĐề xuất tối ưu hóa cho ListView với dữ liệu từ nhiều "bảng"
-------- -------------- ---------
| Tags | | DeviceTags | | Devices |
|--------| |--------------| |---------|
| ID | 1 ------ * | ID | * ------ 1 | ID |
| NAME | | TAGS_ID | | NAME |
-------- | DEVICE_ID | | ... |
-------------- ---------
Mọi thứ được hiển thị trên Trình cung cấp nội dung tôi đã viết. Cho đến nay mọi thứ đều ổn. Trên phần giao diện người dùng, tôi có một ListActivity hiển thị tất cả các thiết bị được lưu trữ (từ bảng Devices) và để tùy chỉnh UI thêm một chút, tôi tạo các mục hàng tùy chỉnh hiển thị một hình ảnh nhỏ ở phía trước dựa trên loại thiết bị v.v.
Điều tôi muốn đạt được bây giờ là cũng hiển thị các thẻ được liên kết trên danh sách đó cho từng thiết bị. Bây giờ ở đây có vấn đề của tôi. Để xem danh sách thiết bị đơn giản, tôi đã tạo ra một ResourceCursorAdapter tùy chỉnh nơi tôi đặt thông tin theo trong phương pháp bindView
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final int objectId = cursor.getInt(cursor.getColumnIndex(Devices._ID));
TextView deviceName = (TextView) view.findViewById(R.id.deviceName);
deviceName.setText(...); //set it from the cursor
...
TextView associatedTagsView = (TextView)...;
associatedTagsView.setText(...); //<<<???? This would need a call to a different table
...
}
Như bạn có thể thấy, để có thể biết những loại thẻ điện thoại của tôi đã liên kết, tôi sẽ cần để truy vấn DeviceTags. Vì vậy, tôi đã làm:
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
...
TextView associatedTagsView = (TextView)view.findViewById(R.id.deviceTags);
String tagsString = retrieveTagsString(view.getContext().getContentResolver(), objectId);
...
}
private String retrieveTagsString(ContentResolver contentResolver, int objectId) {
Cursor tagForDeviceCursor = contentResolver.query(DroidSenseProviderMetaData.TABLE_JOINS.TAG_DEVICETAG,...);
if(tagForDeviceCursor != null && tagForDeviceCursor.moveToFirst()){
StringBuffer result = new StringBuffer();
boolean isFirst = true;
do{
if(!isFirst)
result.append(", ");
else
isFirst = false;
result.append(retrieve name from cursor column...);
}while(tagForDeviceCursor.moveToNext());
return result.toString();
}
return null;
}
Tôi đã thử nghiệm điều này và nó thực sự hoạt động tốt, nhưng phải trung thực tôi không cảm thấy tốt khi làm điều này. Bằng cách nào đó có vẻ lạ đối với tôi ...
Có giải pháp nào tốt hơn về cách giải quyết vấn đề này không ??
// Edit:
Sau phản hồi CommonsWare ở đây một chút làm rõ. Tôi kỳ lạ về việc thực hiện truy vấn thứ hai cho DB bên trong CursorAdapter, về cơ bản điều này sẽ dẫn đến một truy vấn mỗi hàng và tôi lo sợ điều này sẽ ảnh hưởng lớn đến hiệu suất của tôi (tôi vẫn thử nghiệm nó trên một thiết bị thực với một số lượng đáng kể dữ liệu để xem mức độ ảnh hưởng này).
Câu hỏi của tôi do đó là về việc liệu có một số chiến lược về cách tránh cho mô hình dữ liệu của tôi này hay tôi phải về cơ bản "sống" với điều đó :)
Xin lỗi vì câu hỏi mơ hồ của tôi. Không nhận ra điều đó và sửa nó ngay bây giờ. Nhưng bạn hoàn toàn phù hợp với các vấn đề của tôi (+1 cho điều đó) :) Hiệu suất là chính xác điều. Nhưng với yêu cầu rằng 1 thiết bị có thể có nhiều thẻ, tôi sẽ phải đi với thiết kế DB được hiển thị ở trên ... Tất nhiên những gì tôi có thể làm là bằng cách nào đó "hợp nhất" DeviceTags và Tags nhưng tôi đoán điều này sẽ trở nên khá xấu xí ... Có lẽ tôi nên tham gia mọi thứ trên cấp độ ContentProvider Tôi đã có sẵn dữ liệu ... Tôi sẽ thử rằng nếu tôi thấy các giải pháp hiện tại tác động mạnh đến hiệu suất. – Juri
Tôi cũng sẽ cố gắng tránh truy vấn thứ hai trong bộ điều hợp. Chỉ cần xây dựng nhà cung cấp nội dung của bạn theo cách mà tất cả các dữ liệu cần thiết trong danh sách có mặt tại thời điểm nó được hiển thị cho người dùng. – Janusz
@Juri: "Nhưng với yêu cầu 1 thiết bị có thể có nhiều thẻ, tôi sẽ phải đi với thiết kế DB được hiển thị ở trên" - không, bạn không cần. Bạn chỉ cần rằng nếu bạn cũng đang đi vào dữ liệu từ phía thẻ, và thường xuyên, đủ để làm cho nó đáng giá. Cách thay thế của bạn là để chuẩn hóa dữ liệu, có danh sách các thẻ được phân tách bằng dấu phẩy là một cột trong bảng thiết bị. – CommonsWare