Я просмотрел множество примеров/руководств по использованию SQLite в Android. Скажем, у вас есть приложение, которое использует SQLite, ContentProvider
, CursorLoader
, пользовательский CursorAdapter
.
Теперь все основные примеры этого, которые я нашел, полагаются на CursorLoader
для извлечения данных в CursorAdapter
, которые по характеру CursorLoader
выполняются в потоке Async-UI потоком. Тем не менее, эти же примеры делают сообщения о вставке/удалении/обновлении через ContentResolver
в основном потоке (например, от onClick
, onResume
, onPause
). (Пример) Они не переносят эти вызовы в AsyncTask
или запускают отдельный поток или используют AsyncQueryHandler
.
Почему это так, как может так много хорошо написанных блогов/примеров сделать такую очевидную ошибку? Или просто однострочные вставки/удаления/обновления одной строки так быстро, что они достаточно безопасны для запуска из потока Main/UI? Каким образом можно выполнять эти быстрые вызовы?
Android - SQLite ContentResolver вставка/удаление/обновление в потоке пользовательского интерфейса?
Ответ 1
Я также запутался в том, что образцы, вызывающие вызовы в основном потоке. Я думаю, что образцы просто упростили демонстрации, избегая дополнительных потоков и обратных вызовов, поскольку один вызов insert/update/delete может быстро вернуться.
Помимо шаблона Loader для запроса, андроид действительно предоставлял вспомогательный класс AsyncQueryHandler, поскольку API-уровень 1 для операций async CRUD с полными обратными вызовами CRUD. AsyncQueryHandler работает внутри с HandlerThread для операций async и возвращает результаты в основной поток.
Поэтому я уверен, что запросы ContentProvider должны выполняться в рабочих потоках, отличных от пользовательского интерфейса, и эти образцы не могут быть лучшими практиками в соответствии с официальным дизайном.
=== edit
Нашел аннотацию из официальных документов документации, см. this или this, строка 255:
In practice, this should be done in an asynchronous thread instead of
on the main thread. For more discussion, see Loaders. If you are not
just reading data but modifying it, see {@link android.content.AsyncQueryHandler}.
=== edit 2 Ссылка в фактическое руководство разработчика Android, содержащее приведенную выше цитату
Ответ 2
Этот вопрос был на мой взгляд с давних времен. Я думаю, это зависит от сложности файла, который мы пытаемся вставить, обновить или удалить. Если наше приложение будет вставлять или обновлять большие файлы, всегда было бы правильно делать это асинхронно, и если файлы не будут такими большими, запуск его в потоке пользовательского интерфейса может быть выполнен.
Однако всегда рекомендуется продолжать операции с базой данных в отдельном потоке.
Ответ 3
Я думаю, вы ответили на свой вопрос. Я верю, что CursorLoader расширяет AsyncTaskLoader. Вызовы, сделанные из потока пользовательского интерфейса, обрабатывают только вызов TO CusorLoader (который использует AsyncTask.) То, что делается, по-прежнему не выполняется в потоке пользовательского интерфейса. Выполнение вызова метода/функции, который затем запускает вещи в отдельном потоке, все еще делает работу в стороне от потока пользовательского интерфейса.
Какая работа, по вашему мнению, происходит в потоке пользовательского интерфейса?
Пожалуйста, покажите журнал отладки, если это возможно, или пример, где вы думаете, что работа выполнена в пользовательском интерфейсе. Этого не должно быть.
Не пытайтесь спорить, просто хотите знать, как вы пришли к выводу о работе пользовательского интерфейса?