use projection to gain 25% of time

This commit is contained in:
Benoit Marty 2020-07-09 10:43:08 +02:00
parent 327a596de5
commit f714566200
1 changed files with 73 additions and 71 deletions

View File

@ -21,7 +21,9 @@ import android.database.Cursor
import android.net.Uri import android.net.Uri
import android.provider.ContactsContract import android.provider.ContactsContract
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import kotlin.system.measureTimeMillis
class ContactsDataSource @Inject constructor( class ContactsDataSource @Inject constructor(
private val context: Context private val context: Context
@ -32,86 +34,86 @@ class ContactsDataSource @Inject constructor(
val result = mutableListOf<MappedContact>() val result = mutableListOf<MappedContact>()
val contentResolver = context.contentResolver val contentResolver = context.contentResolver
contentResolver.query( measureTimeMillis {
ContactsContract.Contacts.CONTENT_URI, contentResolver.query(
null, ContactsContract.Contacts.CONTENT_URI,
/* TODO arrayOf(
arrayOf( ContactsContract.Contacts._ID,
ContactsContract.Contacts._ID, ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.DISPLAY_NAME, ContactsContract.Data.PHOTO_URI
ContactsContract.Data.PHOTO_URI, ),
ContactsContract.Data.MIMETYPE, null,
ContactsContract.CommonDataKinds.Phone.NUMBER, null,
ContactsContract.CommonDataKinds.Email.ADDRESS // Sort by Display name
), ContactsContract.Data.DISPLAY_NAME
*/ )
null, ?.use { cursor ->
null, if (cursor.count > 0) {
// Sort by Display name while (cursor.moveToNext()) {
ContactsContract.Data.DISPLAY_NAME val id = cursor.getLong(ContactsContract.Contacts._ID) ?: continue
) val displayName = cursor.getString(ContactsContract.Contacts.DISPLAY_NAME) ?: continue
?.use { cursor ->
if (cursor.count > 0) {
while (cursor.moveToNext()) {
val id = cursor.getLong(ContactsContract.Contacts._ID) ?: continue
val displayName = cursor.getString(ContactsContract.Contacts.DISPLAY_NAME) ?: continue
val currentContact = MappedContactBuilder( val currentContact = MappedContactBuilder(
id = id, id = id,
displayName = displayName displayName = displayName
) )
cursor.getString(ContactsContract.Data.PHOTO_URI) cursor.getString(ContactsContract.Data.PHOTO_URI)
?.let { Uri.parse(it) } ?.let { Uri.parse(it) }
?.let { currentContact.photoURI = it } ?.let { currentContact.photoURI = it }
// Get the phone numbers // Get the phone numbers
contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, arrayOf(
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", ContactsContract.CommonDataKinds.Phone.NUMBER
arrayOf(id.toString()), ),
null) ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
?.use { innerCursor -> arrayOf(id.toString()),
while (innerCursor.moveToNext()) { null)
innerCursor.getString(ContactsContract.CommonDataKinds.Phone.NUMBER) ?.use { innerCursor ->
?.let { while (innerCursor.moveToNext()) {
currentContact.msisdns.add( innerCursor.getString(ContactsContract.CommonDataKinds.Phone.NUMBER)
MappedMsisdn( ?.let {
phoneNumber = it, currentContact.msisdns.add(
matrixId = null MappedMsisdn(
) phoneNumber = it,
) matrixId = null
} )
)
}
}
} }
}
// Get Emails // Get Emails
contentResolver.query( contentResolver.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI, ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null, arrayOf(
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", ContactsContract.CommonDataKinds.Email.DATA
arrayOf(id.toString()), ),
null) ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
?.use { innerCursor -> arrayOf(id.toString()),
while (innerCursor.moveToNext()) { null)
// This would allow you get several email addresses ?.use { innerCursor ->
// if the email addresses were stored in an array while (innerCursor.moveToNext()) {
innerCursor.getString(ContactsContract.CommonDataKinds.Email.DATA) // This would allow you get several email addresses
?.let { // if the email addresses were stored in an array
currentContact.emails.add( innerCursor.getString(ContactsContract.CommonDataKinds.Email.DATA)
MappedEmail( ?.let {
email = it, currentContact.emails.add(
matrixId = null MappedEmail(
) email = it,
) matrixId = null
} )
)
}
}
} }
}
result.add(currentContact.build()) result.add(currentContact.build())
}
} }
} }
} }.also { Timber.d("Took ${it}ms to fetch ${result.size} contact(s)") }
return result return result
.filter { it.emails.isNotEmpty() || it.msisdns.isNotEmpty() } .filter { it.emails.isNotEmpty() || it.msisdns.isNotEmpty() }