mobile fest#spb 2012
DESCRIPTION
Секреты удобного хранения данныхTRANSCRIPT
Android:Секреты удобного хранения данных
Дмитрий Викторович МалыхановDataArt
http://www.dataart.com/
● Shared Preferences● Internal/External Storage● SQLite Databases
● Content Provider
Способы хранения данных
http://goo.gl/r673r
● Унифицированный интерфейс● Асинхронные уведомления● Маскировка деталей реализации● Прозрачное хранение файлов● Безопасность● Работа в отдельном процессе
ПреимуществаContent Provider
● IPC вызовы (marshalling)● Кажущееся усложнение кода● Надуманные проблемы с транзакциями
Осложнения
"Вечный" сервис
SQLite Динамическая типизация(читайте: строковые данные)
"Под капотом"
http://goo.gl/igQqT
Инициализация должна быть БЫСТРОЙ!
см. ContentProvider.onCreate() javadoc
Оптимизация:Шаг первый
http://goo.gl/pdBY5
Разгружаем UI thread:
Избегайте лишних преобразований типов!
Оптимизация:Шаг второй
Практически бесполезно
рекомендация:только в сочетании с CASCADE
Оптимизация:Внешние ключи
VIEW вместо сложных JOIN'ов
значительное упрощение кода
Оптимизация:Соединения
Все обращения кContentProvider вне UI thread!
AsyncTask, Handler,AsyncQueryHandler
LoaderManager
Оптимизация:AsyncQueryHanlder
http://goo.gl/1fpOi
Категории:● Item● Directory
Идентификатор категории в ID UriMatcher'а
Оптимизация:Упрощение кода
http://goo.gl/A1wqF
int MASK_TYPE = 0x0000000F;
int TYPE_ITEM = 0x00000001;
int TYPE_DIR = 0x00000002;
...
switch (matcher.match(uri) & MASK_TYPE) {
case TYPE_ITEM:
return "vnd.android.cursor.item/NAME";
case TYPE_DIR:
return "vnd.android.cursor.dir/NAME";
...
Пример:Категории в ID
Зачастую данные изменяются только на сервере:
int rows = resolver.update(...)
if (0 == rows) {
resolver.insert(...);
}
Оптимизация:Конфликты
SQLiteDatabase:
public long insertWithOnConflict (String table,
String nullColumnHack,
ContentValues initialValues,
int conflictAlgorithm)
SQLiteDatabase.CONFLICT_REPLACE
API 8+
Разрешение конфликтов
http://goo.gl/dU1fo
Архитектурные проблемы!
Загрузите XML/CSV в Provider:
ContentResolver.openOutputStream(uri, mode)
ContentProvider.openFileDescriptor(uri, mode)
Большой импорт:Маскировка проблем
http://goo.gl/UlJInhttp://goo.gl/VOF9m
Batch Access:
ContentProviderResult[] applyBatch (String authority, ArrayList<ContentProviderOperation> operations)
Расход памяти!
Большой импорт:Решение
http://goo.gl/1AX8Q
android.net.Uri:● scheme● authority● path● fragment● query
Вся сила URI
http://goo.gl/bSwjG
Перерасход ресурсов UI thread
Решение:Пропускать ненужные уведомления
Content Provider:Уведомления
final static String FRG_SKIP_NOTIFY =
"skip-notify";
...
private boolean isNotifyRequired(Uri uri) {
return !FRG_SKIP_NOTIFY.equals(
uri.getFragment());
}
Пропускаем уведомления (1/3)
public int update(Uri uri, ...) {
...
int rows = ... update ...;
if (rows > 0 && isNotifyRequired(uri)) {
resolver.notifyChange(uri, null);
}
...
Пропускаем уведомления (2/3)
// client code, e.g. your networking service
Uri uri = ... Uri.Builder ...
.fragment(FRG_SKIP_NOTIFY);
...
// build batch of ops with uri
resolver.applyBatch(...);
resolver.notifyChange(uri, null);
Пропускаем уведомления (3/3)
http://goo.gl/FLbVX
Дополнительные данные:
Uri:● fragment● query
ContentResolver:● openOutputStream
Оптимизация:Шаг последний
Android:Секреты удобного хранения данных
ВОПРОСЫ ?
Android:Секреты удобного хранения данных
Дмитрий Викторович МалыхановDataArt
http://www.dataart.com/