Comments 16
Статья годная, но уж очень для новичков. И, как мне кажется, от новичка.
Прокомментирую пункт про потоки:
Наверное, имелись ввиду классы, именуемые AsyncTask, Loader и прочие, и вызывались в них методы execute() да и только.
В разных версиях ос Аndroid используется разный по характеристикам Executor по умолчанию — THREAD_POOL_EXECUTOR.
В какой-то версии один поток и большая очередь, в какой-то 5 и т.д.
В системе только при старте процесса для него сразу же создается 9 потоков и никто из них не ждет своей очереди:
А вот Runnable, которые вы пробрасываете на Executor по умолчанию, будут становиться в очередь, если в пуле свободных потоков больше нету.
Если не хотите зависеть от версии ОС, то задайте своё поведение — запускайте AsyncTask на своём Executor при помощи метода
Прокомментирую пункт про потоки:
Наверное, имелись ввиду классы, именуемые AsyncTask, Loader и прочие, и вызывались в них методы execute() да и только.
В разных версиях ос Аndroid используется разный по характеристикам Executor по умолчанию — THREAD_POOL_EXECUTOR.
В какой-то версии один поток и большая очередь, в какой-то 5 и т.д.
В системе только при старте процесса для него сразу же создается 9 потоков и никто из них не ждет своей очереди:
main
GC
Signal Catcher
JDWP
ReferenceQueueDaemon
FinalizerDaemon
FinalizerWatchdogDaemon
Binder_1
Binder_2
Несмотря на то, что потоков в андройде может быть достаточно много, тем не менее следует понимать что с 5-го по 10-й поток будут стоять в очереди, более того, если поток встал в очередь он не будет запущен параллельно при последующем наличии вакантных мест.Потоки не будут стоять в очереди, они будут выполняться.
А вот Runnable, которые вы пробрасываете на Executor по умолчанию, будут становиться в очередь, если в пуле свободных потоков больше нету.
Если не хотите зависеть от версии ОС, то задайте своё поведение — запускайте AsyncTask на своём Executor при помощи метода
aTask.executeOnExecutor(YOUR_EXECUTOR);
Да уж, про потоки повеселило :)
Я бы добавил, что не нужно использовать AsyncTask в принципе, т.к. он заставляет писать логику (doInBackround) и управление Ui (onPreExecute, onPostExecute) в одном месте, что не здраво, лучше логику писать на уровне модели, а в контроллерах (Activity, Fragment) только слушателей результата.
К тому же, у AsyncTask не предусмотрен механизм обработки ошибок и от версии к версии они меняют поведение THREAD_POOL_EXECUTOR.
Я бы добавил, что не нужно использовать AsyncTask в принципе, т.к. он заставляет писать логику (doInBackround) и управление Ui (onPreExecute, onPostExecute) в одном месте, что не здраво, лучше логику писать на уровне модели, а в контроллерах (Activity, Fragment) только слушателей результата.
К тому же, у AsyncTask не предусмотрен механизм обработки ошибок и от версии к версии они меняют поведение THREAD_POOL_EXECUTOR.
Google советуют использовать Loader для асинхронных операций, как замену класса AsyncTask — не нужно проверять, закрыта уже наша Activity или нет при обновлении UI, нужно ли перезапросить данные при повороте экрана и т.д.
Хранить модель вне Activity я бы не советовал, так как они очень шустро уничтожаются системой при нехватке памяти.
Конечно же это мое скромное мнение, но хранить глобальные динамические данные нужно в Application, постоянные обязательно в SQLite, а все Activity зависимые данные в ней же и хранить с учетом того, что данные могут потеряться.
В защиту AsyncTask — можно использовать их так (так используются классы Loader, но с привязкой к циклу жизни Activity):
Если хотите данные хранить в модели, и чтобы модель обновляла UI, делайте так:
Код грязный, но суть я думаю понятна.
Хранить модель вне Activity я бы не советовал, так как они очень шустро уничтожаются системой при нехватке памяти.
Конечно же это мое скромное мнение, но хранить глобальные динамические данные нужно в Application, постоянные обязательно в SQLite, а все Activity зависимые данные в ней же и хранить с учетом того, что данные могут потеряться.
В защиту AsyncTask — можно использовать их так (так используются классы Loader, но с привязкой к циклу жизни Activity):
@Override
protected Object doInBackground(Object[] params) {
return yourModel.anyAction();
}
@Override
protected void onPostExecute(Object o) {
// update UI here
}
Если хотите данные хранить в модели, и чтобы модель обновляла UI, делайте так:
public void anyAction(Object yourUI){
new AsyncTask() {
@Override
protected Object doInBackground(Object[] params) {
return anyData;
}
@Override
protected void onPostExecute(Object o) {
yourUI.updateWithData(o);
}
}.executeOnExecutor(YOUR_EXECUTOR);
}
Код грязный, но суть я думаю понятна.
Да, все верно, инструкция для совсем новичков, от новичка, который только-только усвоил самые азы разработки на Android :)
Спасибо, про потоки буду иметь ввиду, не знал
Спасибо, про потоки буду иметь ввиду, не знал
К сожалению, executeOnExecutor() появился только в API 11. Хотя сейчас уже меньше заботятся о поддержке старых версий.
Вообще, стоит убрать абзац про потоки в статье, либо основательно переделать. Информация в нем касается только AsyncTask, да и то не совсем верная.
Вообще, стоит убрать абзац про потоки в статье, либо основательно переделать. Информация в нем касается только AsyncTask, да и то не совсем верная.
А модно поподробнее про медленность SQLite? Я читал ровно наоборот.
И еще, я бы еще упомянул о статических анализаторах кода, как помощь к комплексному тестированию. Если модульное тестирование вещь не особо простая, то статический анализатор довольно прост, а выгоды в нём достаточно много. Тот же Lint что идет вместе с AndroidStudio умеет находить захардкоденные строки и многое другое.
Немного оффтопа. Как лучше именовать строки в ресурсах, чтобы это было понятно? У меня сейчас с этим честно говоря хаос. С именованием XML файлов и всего что связано с Java кодом, я уже выработал свою методику на основе книги Совершенный код и Code convention. Но вот с такой простой вещью как строки, пока ума не приложу.
И еще, я бы еще упомянул о статических анализаторах кода, как помощь к комплексному тестированию. Если модульное тестирование вещь не особо простая, то статический анализатор довольно прост, а выгоды в нём достаточно много. Тот же Lint что идет вместе с AndroidStudio умеет находить захардкоденные строки и многое другое.
Немного оффтопа. Как лучше именовать строки в ресурсах, чтобы это было понятно? У меня сейчас с этим честно говоря хаос. С именованием XML файлов и всего что связано с Java кодом, я уже выработал свою методику на основе книги Совершенный код и Code convention. Но вот с такой простой вещью как строки, пока ума не приложу.
SQLite безусловно быстрый :) Медленный он только в ситуации, когда необходимо прочитать и записать большой объем данных одновременно. Связано это с тем что на устройстве вся БД — это один файл и при записи он блокируется. Как выход, например, грязное чтение. Мы у себя в проекте вообще пришли к такому выходу: храним базу на сервере, на клиент заливаем сразу готовой и сохраняем, благо набор данных меняется очень редко.
На счет строк, мы храним их как [название модуля]_[элеменет]_[действие, если есть необходимость]. Пришли к этому, когда возникла проблема как у вас.
На счет строк, мы храним их как [название модуля]_[элеменет]_[действие, если есть необходимость]. Пришли к этому, когда возникла проблема как у вас.
Я не совсем понял ваш пассаж про визуальный конструктор. По большой частью конструктор лишнего ничего не пишет. А ваш пример какой-то дикий. Это не конструктор накидал столько мусора, а сам программист. С таким же успехом он может это написать и вручную, если не понимает, как работает верстка.
Безусловно, пройтись по XML-коду потом желательно, но для быстрого наброска экрана визуальный конструктор вполне рабочий инструмент.
Безусловно, пройтись по XML-коду потом желательно, но для быстрого наброска экрана визуальный конструктор вполне рабочий инструмент.
Полностью согласен. За все три года разработки под Android всегда начинаю верстку с визуального редактора. Но редактировать верстку, конечно, чаще всего проще непосредственно в XML.
Мне тоже не понятны упреки в сторону визуального редактора. Если программист захочет сделать говноверстку, он ее сделает и в текстовом редакторе. А визуальный редактор удобен прежде всего не отображением экрана устройства, а полезными панельками, где показана иерархия элементов и их параметры. Куда удобнее ведь просто поставить чекбокс или выбрать нужный ресурс из диалогового окна, чем писать вручную (пусть и с автодополнением).
Помню где-то читал, что не рекомендуется делать вложенные LinearLayout. А что лучше делать: RelativeLayout или же LinearLayout со вложенным LinearLayout?
основная проблема в том, что невозможно померить за один проход LinearLayout (LL) в котором есть веса. Все элементы, у которых есть веса будут мерится два раза. Если будут вложенные LL, то количество измерений будет расти экспоненциально. например LL1 содержит в качестве ребенка LL2 у которого стоит вес. Все дети LL1 у которых нет веса измерятся один раз, у которых есть измерятся два раза. Все дети LL2 у которых нет весов измерятся два раза, а у которых он есть уже 4 раза. померить некоторые вью довольно тяжело.
RelativeLayout расставляет все за один проход, но этот проход довольно сложный.
поэтому конкретно ответить на этот вопрос нельзя.
часто лучше написать кастомный контролл, который все по-быстрому расставит. чем пытаться собрать лейаут из универсальных блоков.
RelativeLayout расставляет все за один проход, но этот проход довольно сложный.
поэтому конкретно ответить на этот вопрос нельзя.
часто лучше написать кастомный контролл, который все по-быстрому расставит. чем пытаться собрать лейаут из универсальных блоков.
Если все ваши View строго позиционированы
так и пишите, что если координаты вью в пикселях (pt/mm/dp/sp), либо достаточно стандартной gravity. Что такое «строго» в вашем варианте хрен поймешь.
Margin – отъедает место у самого элемента, padding – у окружения
это вообще все неверно. Margin это отступы, которые учитывает родительский элемент при позиционировании ребенка, у которого задано Margin. Не все ViewGroup поддерживают Margin и на размер ребенка Margin напрямую не влияет. Так как Margin не принадлежит геометрии ребенка, то и клики ребенку не доходят из этой области, они идут родителю. Padding же работает подругому. Сама View, у которой он задан занимается его расчетом. Например, view не учитывает паддинг когда рисует свой фон, но учитывает его и делает отступы для своего содержимого.
Sign up to leave a comment.
Мелочи разработки на Android для начинающих