我需要从手机的联系人列表数据库中拆分联系人。如果用户有很多联系人加载卡住几秒钟来加载不太好的东西。我想用Rx将其除以一次加载20个联系人,但是在启动时加载所有联系人,而不是延迟加载。在这一刻,我尝试了带有concat的observables,但它收集了所有结果并在完成所有结果后返回,而不是在获得它们之后返回每20个联系人,并在返回后继续下一包联系人。这个实现有什么问题?
@Override public Observable<List<Contact>> getPhoneContacts() {
return Observable.fromCallable(this::getCursor)
.concatMap(cursor -> {
List<Observable<List<Contact>>> list = new ArrayList<>();
int pagesCount = cursor.getCount()/20 + 1;
for(int i = 0; i < pagesCount; i++){
list.add(Observable.just(getContactList(cursor)));
}
return Observable.concat(list).compose(upstream -> {
cursor.close();
return upstream;
});
});
}
private List<Contact> getContactList(Cursor cursor) {
List<Contact> contacts = new ArrayList<>();
if (cursor != null && !cursor.isClosed() && areContactsPresent(cursor)) {
while (contacts.size() < 20){
if (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Contact contact = getContact(cursor, id);
if (contact != null) {
contacts.add(contact);
}
}
//else {
// cursor.close();
// break;
//}
}
}
return contacts;
}
private Cursor getCursor(){
return contentResolver.query(ContactsContract.Contacts.CONTENT_URI,
null, ContactsContract.Data.HAS_PHONE_NUMBER+">0", null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
}
private Contact getContact(Cursor cursor, String id) {
Contact contact = null;
Cursor phonesCursor = contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
if (phonesCursor != null) {
while (phonesCursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME));
String phoneNo = phonesCursor.getString(
phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if (!phoneNo.isEmpty()) {
contact = Contact.create(name, phoneNo);
}
}
phonesCursor.close();
}
return contact;
}
答案 0 :(得分:0)
您的可观察需求看起来像那样
Observable.create((ObservableOnSubscribe<List<Contact>>) emitter -> {
int pagesCount = cursor.getCount()/20 + 1;
for(int i = 0; i < pagesCount; i++){
emitter.onNext(getContactList(cursor)); // Passes list with 20 items to onNext()
}
emitter.onComplete();
});
您的数据源现在返回List<Contact>
而不是单个Contact
,这意味着每个排放都会为您提供一个联系人列表,每个列表根据您的实现有20个项目。
然后,您可以使用每次发射更新UI,而不是等待加载所有联系人。