10

Я просмотрел множество примеров/руководств по использованию SQLite в Android. Допустим, у вас есть приложение, которое использует SQLite, ContentProvider, CursorLoader, обычай CursorAdapter. Теперь все основные примеры этого, которые я нашел, полагаются на CursorLoader для извлечения данных в CursorAdapter, который по характеру CursorLoader происходит в безопасном потоке Async-UI. Тем не менее, эти же примеры делают сообщения о вставке/удалении/обновлении через ContentResolver на основной нити (например, от onClick, onResume,). (Example) Они не переносят эти вызовы в AsyncTask или запускают отдельный поток или используют AsyncQueryHandler. Почему это так, как может так много хорошо написанных блогов/примеров сделать такую ​​очевидную ошибку? Или просто однострочные вставки/удаления/обновления одной строки так быстро, что они достаточно безопасны для запуска из потока Main/UI? Каков правильный способ совершать эти быстрые звонки?Android - SQLite ContentResolver вставка/удаление/обновление в потоке пользовательского интерфейса?

+1

ваше последнее предложение, вероятно, правильно: операция запроса наверняка намного сложнее, чем отдельная вставка/обновление/удаление. – pskink

ответ

4

Я также путался с образцами, делающими звонки по основной теме. Я думаю, что образцы просто упростили демонстрации, избегая дополнительных потоков и обратных вызовов, поскольку один вызов insert/update/delete может быстро вернуться.

Помимо шаблона Loader для запроса, андроид предоставил вспомогательный класс AsyncQueryHandler, поскольку API-уровень 1 для операций async CRUD с полным обратным вызовом CRUD поддерживается. AsyncQueryHandler работает внутри с HandlerThread для операций async и возвращает результаты в основной поток.

Таким образом, я уверен, что запросы ContentProvider должны выполняться в рабочих потоках, отличных от пользовательского интерфейса, и эти образцы не могут быть лучшими практиками в соответствии с официальным дизайном.

=== редактировать

Найдена аннотацией из официальных рамочных документов см this или this, Line 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}. 

=== редактировать 2 Link к фактическому андроиду Dev руководству, содержащему выше цитаты

+0

Правильно, я также упомянул AsyncQueryHandler о моем вопросе ... это все еще не очень убедительно, что ВСЕ учебники и примеры, которые я пришел через это, просто потому, что он проще и даже не упоминает, что это не то, как вы должны это делать. Для правильного ответа я хотел бы получить что-то официальное от Google (член команды, doc, учебник) или что-то в этом роде (возможно, ссылка на респектабельный проект GitHub, который делает это так или иначе), что делает эти светлые звонки на Главная тема, или использует что-то вроде AsyncQueryHandler ... –

+0

Иначе все остальное просто наше мнение по этому поводу ... :) –

+0

@LeoK Получил официальный документ, который упоминал об этом. См. Мои правки. –

2

Этот вопрос был на мой взгляд с давних времен. Я думаю, это зависит от сложности файла, который мы пытаемся вставить, обновить или удалить. Если наше приложение собирается вставлять или обновлять большие файлы, всегда было бы правильно делать это асинхронно, и если файлы не будут такими большими, запуск этого файла в потоке пользовательского интерфейса может быть выполнен.

Однако всегда рекомендуется продолжать операции с базой данных в отдельном потоке.

+0

Спасибо за ответ. Это не совсем объясняет, почему Учебники, которые объясняют лучшие практики и в других аспектах, делают вещи правильно/безопасно в случае вставки/удаления/обновления, никогда не беспокоятся об отдельных потоках. Очевидно, что я не прочитал все хорошие учебные пособия, поэтому можно было бы приветствовать хорошие примеры встречных примеров. (Особенно из Google или других авторитетных источников) –

0

Я думаю, вы ответили на свой вопрос. Я верю, что CursorLoader расширяет AsyncTaskLoader. Вызовы, сделанные из потока пользовательского интерфейса, обрабатывают только вызов TO CusorLoader (который использует AsyncTask.) То, что делается, по-прежнему не выполняется в потоке пользовательского интерфейса. Выполнение вызова метода/функции, который затем запускает вещи в отдельном потоке, все еще делает работу вне потока пользовательского интерфейса.

Какая работа, по вашему мнению, происходит в потоке пользовательского интерфейса?

Пожалуйста, покажите журнал отладки, если это возможно, или пример, где вы думаете, что работа выполнена в пользовательском интерфейсе. Не должно быть.

Не пытайтесь утверждать, просто хотите знать, как вы пришли к выводу о работе пользовательского интерфейса?

+0

Вы правы, когда загрузчик курсора является асинхронным. Вот что я написал в этом вопросе. Однако вызовы вставки/удаления/обновления выполняются через ContentReslover, а не с CursorLoader. Все, что происходит через ContentReslover, выполняется в потоке пользовательского интерфейса, если вызов его выполняется в потоке пользовательского интерфейса. Это легко проверить, просто добавив Thread.sleep (5000) в начало переопределения вставки вашего ContentProvider. Если вы это сделаете, вы увидите, что ваш UI замерзает в течение 5 секунд ... –

Смежные вопросы