2016-06-06 9 views
0

In meiner App versuche ich alle Kontakte im lokalen Geschäft beim Öffnen zu speichern. Mein Code funktioniert hervorragend, wenn nicht zu viele Kontakte verfügbar sind. Wenn es jedoch mehr als 100 Kontakte gibt, dauert es ewig, sie alle zu speichern. Ich benutze Realm - ein DB-Framework, um jeden Kontakt in ein Modellobjekt umzuwandeln. Dies ist die Asynchron-Aufgabe, die ausgeführt wird, wenn mein app öffnet erstenDas Laden von Kontakten und das Speichern in Realm dauert sehr lange

private class AppOpeningAsyncTask extends AsyncTask<Void,Void,Void> { 

    // Operations performed in the background. 
    @Override 
    protected Void doInBackground(Void... params) { 

     // Retrieving and saving users contacts 
     Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); 
     while (phones.moveToNext()) 
     { 
      String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); 
      String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
      Contact.createOrUpdateWithNameAndNumber(name, phoneNumber, (RoofActivity) mContext); 
     } 
     phones.close(); 

     return null; 
    } 

    // Operations performed on UI thread. 
    @Override 
    protected void onPostExecute(Void aVoid) { 
     super.onPostExecute(aVoid); 

     enterApp(); 

    } 
} 

Und hier ist mein Kontakt Reich-Objekt:

public class Contact extends RealmObject { 

private String name; 

@PrimaryKey 
private String number; 

public static void createOrUpdateWithNameAndNumber(final String name, final String number, final RoofActivity activity){ 

    ((Activity)activity).runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 

      Realm realm = activity.getRealmInstance(); 
      Contact contact = realm 
        .where(Contact.class) 
        .equalTo("name", name) 
        .equalTo("number", number) 
        .findFirst(); 

      if (contact == null) { 
       contact = new Contact(); 
      } 

      realm.beginTransaction(); 

      contact.setName(name); 
      contact.setNumber(number); 

      realm.copyToRealmOrUpdate(contact); 
      realm.commitTransaction(); 
     } 
    }); 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public String getNumber() { 
    return number; 
} 

public void setNumber(String number) { 
    this.number = number; 
} 

}

Es ist wichtig zu beachten, dass ich nur zu retten versuchen MOBILE-Nummern. Gibt es eine Möglichkeit, diesen Code zu optimieren? Oder gibt es andere Ansätze, um diese Informationen effizienter abzurufen? Venmo scheint das nahtlos zu schaffen.

Antwort

1

Sie sollten eine einzige Schreibtransaktion für alle Ihre Aktualisierungen und nicht eine pro Einfügung verwenden, und Sie sollten Ihre Aktualisierungen nicht an den UI-Thread senden.

Realm hat einen gewissen Overhead pro Transaktion, und wenn Sie nur ein einzelnes Objekt pro Transaktion einfügen, wird dieser Aufwand massiv größer sein als die Zeit, die tatsächlich für das Einfügen dieses Objekts aufgewendet wird. Das Einfügen von 100 Objekten in einer einzigen Transaktion wird wahrscheinlich weniger Zeit benötigen als zwei Transaktionen, die jeweils nur ein einzelnes Objekt einfügen.

Das Veröffentlichen Ihrer Aktualisierungen im UI-Thread ist das genaue Gegenteil dessen, was Sie tun möchten. Sie sollten versuchen, vermeiden Schreibvorgang auf dem UI-Thread ausführen, nicht aus dem Weg, dies zu tun, wenn es keinen Grund zu tun.

+0

Wenn ich versuche, diese Objekte im Hintergrund zu speichern, erhalte ich den folgenden Fehler: Realm-Zugriff von falschem Thread. Auf Realm-Objekte kann nur in dem Thread zugegriffen werden, in dem sie erstellt wurden. –

+0

Gibt 'RoofActivity.getRealmInstance()' eine zwischengespeicherte Instanz zurück? Sie müssen eine Realm-Instanz für den aktuellen Thread in der Hintergrundaufgabe abrufen (und dann 'close()' am Ende der Aufgabe aufrufen). –

+0

Ja, du hast Recht. Realm.getDefaultInstance(), anstatt eine Instanz in der Aktivität zu speichern, löste alle meine Probleme! Der Kontaktabruf ist jetzt etwas schneller, aber immer noch nicht ideal. Irgendwelche Ideen, wie ich das beschleunigen kann? –