Das Abrufen der gesamten Kontaktliste (Name, E-Mail, Telefon) von Android dauert bei etwa 700 Kontakten mehr als eine Minute
Lesezeit: 8 Minuten
Gibt es eine Möglichkeit diese Zeit zu verkürzen? Ich laufe mit dem Cursor und nehme den Namen, Telefonnummern und E-Mails
Wenn ich die Abfrage der Telefonnummern aus der Abfrageschleife entferne, endet sie in 3 Sekunden
Irgendeine Idee, wie ich diese Abfrage verbessern kann?
Mache ich vielleicht etwas falsch in meiner Abfrage?
(Offensichtlich mache ich es asynchron, aber trotzdem … es ist eine sehr lange Zeit, die ein Benutzer nicht warten kann)
Hoffe, jemand kann seine Gedanken dazu teilen
das ist mein Code
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
AddressBookEntity adr = new AddressBookEntity();
String id = cur.getString(cur
.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur
.getString(cur
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
adr.fullName = name;
Cursor emailCur = cr
.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID
+ " = ?", new String[] { id },
null);
while (emailCur.moveToNext()) {
// This would allow you get several email addresses
// if the email addresses were stored in an array
String email = emailCur
.getString(emailCur
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if (!Utils.IsNullOrEmptyString(email)) {
adr.email = email;
}
}
emailCur.close();
if (Integer
.parseInt(cur.getString(cur
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
Cursor pCur = cr
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = ?",
new String[] { id }, null);
int phoneIndex = 0;
while (pCur.moveToNext()) {
String number = pCur.getString(pCur
.getColumnIndex(Phone.NUMBER));
String country = Utils.GetCountryFromNumber(
number, app);
number = Utils.GetFullPhoneNumber(number, app);
if (phoneIndex == 0) {
if (!Utils.IsNullOrEmptyString(number)) {
adr.contactAdressBookId = id;
adr.phoneNumber = number;
adr.userInsertedId = app.userCred.userId;
adr.country = country;
myContacts.add(adr);
}
} else {
if (!Utils.IsNullOrEmptyString(number)) {
AddressBookEntity adrMore = new AddressBookEntity();
adrMore.fullName = adrMore.fullName;
adrMore.country = adrMore.country;
adrMore.email = adrMore.email;
adrMore.phoneNumber = number;
adrMore.contactAdressBookId = id;
adrMore.country = country;
myContacts.add(adrMore);
}
}
}
pCur.close();
}
}
cur.close();
3 Sekunden sind zu viel, es sollte im schlimmsten Fall in einer halben Sekunde erledigt sein
– Pskink
7. November 2014 um 19:16 Uhr
der beigefügte Code dauert fast eine Minute! 3 Sekunden sind ohne Post und Telefone
– itay83
7. November 2014 um 20:41 Uhr
ja ich weiß, 700 Einträge sollten nicht länger als eine Sekunde dauern
– Pskink
7. November 2014 um 20:46 Uhr
Um es zu beweisen, werde ich Ihnen morgen die funktionierende Lösung geben
– Pskink
7. November 2014 um 22:40 Uhr
OMG, ich habe den Hauptcode in meiner Antwort vergessen, versuchen Sie es jetzt und teilen Sie Ihre Ergebnisse mit, ich denke, Sie sollten es in 1/3 Sekunde tun …
– Pskink
9. November 2014 um 8:09 Uhr
pskink
mit dem folgenden Code für 59 Kontakte habe ich folgende Ergebnisse auf dem Emulator erhalten:
D ╔══════ query execution stats ═══════
D ║ got 59 contacts
D ║ query took 0.012 s (12 ms)
D ╚════════════════════════════════════
ok, das war die beste Zeit, aber der Durchschnitt liegt bei 25-35 ms (für 59 Kontakte), fügen Sie den folgenden Code in einen onClick-Callback ein und führen Sie ihn mehrmals ein, um die durchschnittliche Zeit zu erhalten, in Ihrem Fall sollten Sie 30 erhalten * 700 / 59 = ~300-400 ms, nicht 3 Sekunden, geschweige denn eine Minute 😉
es verwendet Uri auf gesetzt Kontaktpersonen.CONTENT_URI in API-Ebene 18 hinzugefügt, aber Sie können verwenden KontakteVertragsdaten.CONTENT_URI beim Erstellen für API-Geräte vor 18
List<AddressBookContact> list = new LinkedList<AddressBookContact>();
LongSparseArray<AddressBookContact> array = new LongSparseArray<AddressBookContact>();
long start = System.currentTimeMillis();
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE,
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
// we could also use Uri uri = ContactsContract.Data.CONTENT_URI;
// ok, let's work...
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIdx);
AddressBookContact addressBookContact = array.get(id);
if (addressBookContact == null) {
addressBookContact = new AddressBookContact(id, cursor.getString(nameIdx), getResources());
array.put(id, addressBookContact);
list.add(addressBookContact);
}
int type = cursor.getInt(typeIdx);
String data = cursor.getString(dataIdx);
String mimeType = cursor.getString(mimeTypeIdx);
if (mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
// mimeType == ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
addressBookContact.addEmail(type, data);
} else {
// mimeType == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
addressBookContact.addPhone(type, data);
}
}
long ms = System.currentTimeMillis() - start;
cursor.close();
// done!!! show the results...
int i = 1;
for (AddressBookContact addressBookContact : list) {
Log.d(TAG, "AddressBookContact #" + i++ + ": " + addressBookContact.toString(true));
}
final String cOn = "<b><font color="#ff9900">";
final String cOff = "</font></b>";
Spanned l1 = Html.fromHtml("got " + cOn + array.size() + cOff + " contacts<br/>");
Spanned l2 = Html.fromHtml("query took " + cOn + ms / 1000f + cOff + " s (" + cOn + ms + cOff + " ms)");
Log.d(TAG, "\n\n╔══════ query execution stats ═══════" );
Log.d(TAG, "║ " + l1);
Log.d(TAG, "║ " + l2);
Log.d(TAG, "╚════════════════════════════════════" );
SpannableStringBuilder msg = new SpannableStringBuilder().append(l1).append(l2);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView tv = new TextView(this);
tv.setTextSize(20);
tv.setBackgroundColor(0xff000033);
tv.setPadding(24, 8, 24, 24);
tv.setText(msg);
ll.addView(tv);
ListView lv = new ListView(this);
lv.setAdapter(new ArrayAdapter<AddressBookContact>(this, android.R.layout.simple_list_item_1, list));
ll.addView(lv);
new AlertDialog.Builder(this).setView(ll).setPositiveButton("close", null).create().show();
der Helfer AddressBookContact Klasse:
Klasse AddressBookContact { private lange ID; private Ressourcen res; privater String-Name; private LongSparseArray-E-Mails; private LongSparseArray-Telefone; AddressBookContact (lange ID, Zeichenfolgenname, Ressourcenres) { this.id = id; this.name = Name; this.res = res; } @Override public String toString() { return toString(false); } Public String toString (boolean rich) { SpannableStringBuilder builder = new SpannableStringBuilder(); if (rich) { builder.append("id: ").append(Long.toString(id)) .append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m");
} else {
builder.append(name);
}
if (phones != null) {
builder.append("\n\tphones: ");
for (int i = 0; i < phones.size(); i++) {
int type = (int) phones.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
.append(": ")
.append(phones.valueAt(i));
if (i + 1 < phones.size()) {
builder.append(", ");
}
}
}
if (emails != null) {
builder.append("\n\temails: ");
for (int i = 0; i < emails.size(); i++) {
int type = (int) emails.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
.append(": ")
.append(emails.valueAt(i));
if (i + 1 < emails.size()) {
builder.append(", ");
}
}
}
return builder.toString();
}
public void addEmail(int type, String address) {
if (emails == null) {
emails = new LongSparseArray<String>();
}
emails.put(type, address);
}
public void addPhone(int type, String number) {
if (phones == null) {
phones = new LongSparseArray<String>();
}
phones.put(type, number);
}
}
Thanks alot gonna try that 🙂 will get back to you with my results
– itay83
Nov 9, 2014 at 8:26
and? what was your results?
– pskink
Nov 9, 2014 at 15:57
not yet I’m on some other project will get back to check this later i’ll keep you posted 🙂 and thanks again! from what I see from u’re results my 700 contacts should load in few seconds hope this will actually be the result
– itay83
Nov 9, 2014 at 18:02
Hey it’s working great!!! 11-11 10:00:08.907: D/TAG(32169): ╔══════ query execution stats ═══════ 11-11 10:00:08.907: D/TAG(32169): ║ got 959 contacts 11-11 10:00:08.917: D/TAG(32169): ║ query took 1.985 s (1985 ms) 11-11 10:00:08.917: D/TAG(32169): ╚════════════════════════════════════ Thanks alot! gonna use it :))
– itay83
Nov 11, 2014 at 8:01
@MarkoGajić this is normal, most users blindly use ^C / ^V without any 5 minute reflection on how some things could be done better – the best example is hundreds of posts here on how to move / scale / rotate images – they use huge amount of spaghetti code while it can be done using this simple MatrixGestureDetector
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
null, null, null, null);
Dadurch wird die Datenverarbeitung deutlich langsamer. Wenn Sie ein Array von Spalten definieren, die Sie wirklich abrufen müssen, geht es viel schneller.
8902400cookie-checkDas Abrufen der gesamten Kontaktliste (Name, E-Mail, Telefon) von Android dauert bei etwa 700 Kontakten mehr als eine Minuteyes
3 Sekunden sind zu viel, es sollte im schlimmsten Fall in einer halben Sekunde erledigt sein
– Pskink
7. November 2014 um 19:16 Uhr
der beigefügte Code dauert fast eine Minute! 3 Sekunden sind ohne Post und Telefone
– itay83
7. November 2014 um 20:41 Uhr
ja ich weiß, 700 Einträge sollten nicht länger als eine Sekunde dauern
– Pskink
7. November 2014 um 20:46 Uhr
Um es zu beweisen, werde ich Ihnen morgen die funktionierende Lösung geben
– Pskink
7. November 2014 um 22:40 Uhr
OMG, ich habe den Hauptcode in meiner Antwort vergessen, versuchen Sie es jetzt und teilen Sie Ihre Ergebnisse mit, ich denke, Sie sollten es in 1/3 Sekunde tun …
– Pskink
9. November 2014 um 8:09 Uhr