Подтвердить что ты не робот

Android: расширение контактной книги пользователя. Производительность ContentProvider vs Sqlite vs Список в памяти

У меня и моей команды Android есть проблемы. У нас есть приложение, которое представляет контактную книгу пользователя с расширенной информацией.

Текущая настройка

Наше приложение читает Контакты поставщика ОС Android. Отправляет эту информацию на наш Сервер, который вычисляет для нас пару необходимых полей. Эта информация позже извлекается нашим приложением, и мы сохраняем эту информацию в базе данных SQLite. В нашей базе данных мы получаем две таблицы. Один со всеми числами и вся дополнительная информация, которую сервер рассчитывал для нас. Другая таблица - одна со всеми Контактами (один контакт может иметь несколько номеров). Эта таблица контактов создана только для производительности; мы можем выбрать курсор для выбора всех строк в этой таблице контактов в нашем CursorAdapter при представлении контактной книги для пользователя. Следовательно, при представлении контактной книжки пользователю, нам нужно только прочитать нашу собственную базу данных SQLite и только одну таблицу (например, нет JOIN).

Основная проблема

Происходит много синхронизации. Поскольку данные дублируются, нам нужно проверить наличие/изменение/удаление и синхронизировать все время. Более того, когда мы собираемся изменить конкретную вещь в нашем слое презентации, нам нужно изменить нашу таблицу контактов, чтобы включить эту конкретную информацию.

Приоритет для нас

1st: Производительность при представлении контактной книги пользователю.

2nd: поддержка кода.

Следовательно, не комментируйте: "Не дублируйте данные - это корень всех проблем". Для нас более важно то, что у пользователя нет проблем с производительностью, чем если бы мы, как разработчики, потратили дополнительное время на создание хороших алгоритмов синхронизации.

Решения?

Я не знаю почему, но я всегда думал, что CursorAdapter (чтение всех строк из одной таблицы) работает намного лучше, чем ArrayAdapter со списком объектов (хранящихся в памяти). Кто-нибудь знает, верно ли это? Поскольку одно решение, которое поможет нам, по крайней мере, половину пути, заключается в том, чтобы при запуске присоединиться к поставщику контактов (родной телефонной книге) и нашей расширенной информации, сохранить это в списке в памяти и представить его с помощью ArrayAdapter.

Создание собственных поставщиков контента? Я мало знаю о создании собственного поставщика контента. Кто-то пытался создать поставщика контента, который расширяет информацию родной контактной книги и присоединяется к ней. Возможно, с реализацией этого интерфейса: ContactsContract.DataColumnsWithJoins? Кто-нибудь пробовал что-нибудь подобное? Как производительность при представлении этой информации в CursorAdapter?

Пожалуйста, запросите дополнительную информацию, которую я, возможно, забыл, и я обновлю вопрос!

Большое спасибо за все полезные советы и решения!

4b9b3361

Ответ 1

Я пришел к выводу (работая над моим приложением JReader, который много полагается на быстрые операции с БД), что SQLite в Android довольно быстр, как на других платформах, но есть некоторые специфические проблемы Android. Некоторые рекомендации относительно производительности базы данных и заданных вами вопросов:

  • Поставщики контента в основном бесполезны, если вы не планируете делиться своими данными через них. Но они обеспечивают как минимум 2 преимущества. Сначала вы получаете уведомления об изменении данных, и ваш курсор автоматически обновляется, а второй и важный: для CursorLoaders требуется поставщик контента, и если производительность важна для вас, я настоятельно рекомендую использовать их для загрузки курсора;
  • Доступ к коллекциям намного быстрее, чем доступ к базе данных, но это двойная работа, поскольку вам все равно нужно сохранять данные, а доступ к БД довольно быстрый даже для получения данных для супербыстрого списка прокрутки, и особенно из одного таблица, это не должно быть проблемой;
  • Создайте свою БД должным образом (с помощью JOINS, индексов и т.д.):), НО НЕ ИСПОЛЬЗУЙТЕ СОХРАНЕНИЕ ЗАПРОСОВ В КУРСОРНЫХ ЗАПРОСАХ! У меня было много проблем с производительностью на нескольких платформах Android (включая 4.0+), но не всегда. Способ доступа к совместным таблицам - это просто сначала получить внешний ключ, а затем запросить дочернюю таблицу.

По моему опыту, у меня были ситуации, когда производительность БД была очень плохой, но в конце концов мне всегда удалось настроить код и, как результат, увеличился бы в 10-100 раз. Поэтому продолжайте профилировать код DB, и вы обязательно достигнете желаемой производительности.

Ответ 2

Дэн 2-й комментарий верен. Android использует окно курсора под экранами для данных кэша из курсора (около 1 М). см. Android-документы в окне курсора. Как ускоряет переход курсора.

Если вы предпочитаете не присоединяться к двум таблицам отдельно, вы можете рассмотреть CursorJoiner, который работает быстрее. Это может перейти к вашему пользовательскому contentProvider, где один из провайдеров указывает на контакты и возвращает курсор, аналогично второй указывает на ваш собственной таблицы и возвращает курсор. С помощью курсора можно присоединить оба этих курсора.

(Хотя это сложный процесс)