2017-12-08 7 views
0

Ich muss teilen bekommen Kontakte aus Telefon Kontaktliste Datenbank. Wenn der Benutzer viele Kontakte hat, bleibt das Laden für einige Sekunden hängen, um etwas zu laden, was nicht sehr gut ist. Ich möchte es mit Rx teilen, um 20 Kontakte pro Zeit zu laden, aber mit dem Laden aller Kontakte am Anfang, nicht mit dem faulen Laden. In diesem Moment habe ich es mit dem Ziehen von Observablen mit concat versucht, aber es sammelt alle Ergebnisse und kehrt nach dem Beenden aller von ihnen zurück, anstatt alle 20 Kontakte zurückzugeben, nachdem man sie bekommen hat und gleich nach der Rückkehr mit dem nächsten Paket von Kontakten fortfahren. Was ist falsch an dieser Implementierung?Rxjava Split bekommen Kontakte

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

Antwort

0

Sie Quelle beobachtbaren Bedürfnisse etwas wie die

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

Ihrer Datenquelle gibt nun List<Contact> anstelle einer einzigen Contact, zu sehen, was bedeutet, jede Emission Ihnen eine Liste von Kontakten zur Verfügung stellt, wobei jede Liste hat 20 Elemente gemäß Ihrer Implementierung.

Dann können Sie die Benutzeroberfläche mit jeder Ausgabe aktualisieren, anstatt darauf zu warten, dass alle Kontakte geladen werden.

Verwandte Themen