Rxjava分手联系

时间:2017-12-08 10:52:25

标签: android contacts rx-java2

我需要从手机的联系人列表数据库中拆分联系人。如果用户有很多联系人加载卡住几秒钟来加载不太好的东西。我想用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;
  }

1 个答案:

答案 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,而不是等待加载所有联系人。