Программирование под Андроид Archives

Службы (Service)

Службы, сервисы (Service) — задачи, выполняемые в фоне и не  использующие основной (UI) поток, выполняются независимо работает ли запустившее их приложение или нет. О своей работе могут сообщать с помощью уведомления (Notifications). Службы необходимо прописывать в манифесте. У сервиса есть методы : onCreate и onDestroy — срабатывают при создании и уничтожении, onStartCommand — выполнение задачи, onBind — синхронное подключение к сервису. Сервис запускается и останавливается методами startService и stopService, на вход которых идет интент с указанием на класс сервиса. Выполняемую задачу рекомендуется выносить в отдельный поток, для нескольких задач организовывать  схему из нескольких потоков Executors.newFixedThreadPool,  если необходимо чтобы сервис сам себя остановил используются методы stopSelf и stopSelfResult, на вход которых идет startId- номер вызова сервиса.
При нехватке памяти система останавливает сервисы, метод onStartCommand возвращает константу, отвечающую за то будет ли сервис перезапущен: START_NOT_STICKY — не перезапустится, START_STICKY — перезапустится, START_REDELIVER_INTENT — перезапустится и получит все незавершившиеся вызовы. В onStartCommand есть входной параметр flags, который может иметь значения : 0, START_FLAG_RETRY, START_FLAG_REDELIVERY.
Результат работы сервиса можно получить несколькими способами. Во-первых, с помощью PendingIntent: создается он методом createPendingResult  и добавляется к интенту для запуска сервиса, в onSrartCommand читаем его и отправляем данные его методом send в  onActivitiResult. Во-вторых, с помощью BroadcastReceiver, для которого настраиваем IntentFilter на определенное Action и регистрируем   на него (registerReceiver), и реализуем метод onReceive, завершаем сеанс с помощью unregisterReceiver. Третий — синхронный способ взаимодействия с сервисом, реализуется в onBind — биндинг (подключение). Для подключения и отключения используются методы bindService и unbindService. Удобно использовать флаг BIND_AUTO_CREATE, чтобы сервис сам создавался при подключении. Объект ServiceConnection с его методами onServiceConnected и onServiceDisconnected поможет определить их был ли отключен сервис системой при нехватке памяти. Метод onBind возвращает объект с интерфейсом IBinder, для синхронного обмена данными достаточно создать свой класс наследник класса Binder дополнив его новыми методами, а потом тот возвращаемый объект привести к новому типу — такой биндинг может выполняться только в одном процессе и потому называется локальным.

Потоки

 В любом приложении Андроид есть основной поток. Чтобы приложение не зависало лишний раз , не стоит грузить основной поток приложения отвечающий за экран и взаимодействие с пользователем, поэтому все сложные длительные операции необходимо выполнять в отдельном потоке.  Для этого надо создать объект класса Thread и в нем прописать реализацию метода run, а затем запустить наш созданный поток методом start.
Но новый созданный поток не имеет прямого доступа к другим потокам, в том числе к пользовательскому экрану.  В этом нам поможет обработчик очереди сообщений  Handler. Через посылку ему сообщения  можно выполнять операции в другом потоке и делать отложенные по времени операции. Таким образом чтобы получить доступ к экрану из нового потока необходимо создать объект Handler в основном потоке, а из нового потока послать сообщение для Handler на обработку (Handler имеет доступ к экрану). Для обработки сообщения  реализовываем его метод handleMessege() где и прописываем  что необходимо сделать. Так же  Handler может использовать объект,   реализующий интерфейс Handler.Callback с всего одним этим методом. Посылаем из потока сообщение методами sendEmptyMessege ( это простейший метод сам создающий сообщение со всего одним параметром what) или создаем сообщение (объект класса Message) методом obtainMessege (с параметрами int what, int arg1, int arg2 и есть  с Object obj) из глобального пула сообщений и отправляемш методом sendMessage. Напрямую создавать объект Message с помощью конструктора не рекомендуется. Если необходимо отправить сообщение с задержкой (указывается в миллисекундах) используются соответствующие методы sendEmptyMessageDelayed и sendMessageDelayed, причем в течение этого времени его можно будет удалить методом removeMessages. Если необходимо отсчитывать время со времени старта системы, а не посылки сообщения, то используются методы sendEmptyMessageAtTime и sendMessageAtTime, при этом просроченные сообщения выполняются сразу же.
Кроме обработки сообщений Handler может выполнять кусочки кода — объекты класса  Runnable. Для подачи кода используются методы post, postDelayed или runOnUiThead.
В Андроид для упрощения работы с потоками есть специальный класс AsyncTask. Мы создаем объект этого класса вместо создания нового потока и обработчика сообщений. Объект создаем и запускаем (execute) в UI-потоке. И реализуем его методы: doInBackground — в этом методе выполняем тяжелые задачи, а в методах, выполняемых до и после этого метода, —  onPreExecute и onPostExecute имеем доступ к основному (UI) потоку, для вывода промежуточных данных метод onProgressUpdate ( вызывается publishProgress), для отмены задачи метод onCancelled. При создании объекта класса AsyncTask в угловых скобках указываются типы параметров — типы входных (что приходит на вход AsyncTask) , промежуточных (тип данных используемых в методе по выводу  промежуточного результата ) и выходных. Результат можно получить методом get по завершению задачи. Для отмены уже запущенной задачи используется метод cancel , получающий на вход boolean параметр-метку для удаления, а читаем метку в процессе выполнения методом isCancelled. False — если задача отменена или завершена.  Если задача отменена то системой вызовется метод onCancelled вместо onPostExecute. Для задачи можно проверить статус методом getStatus: PENDING (еще не запущена), RUNNING и FINISHED (успешно завершена).

SQLite

Для хранения большого объема данных используйте базу данных SQLite, дающую возможность структурировать данные в таблицы и обрабатывать запросы. При подключении к БД указывается имя БД и номер версии. Для создания и обновления версии БД и вообще для работы нужно создать класс наследник SQLiteOpenHelper с его методами onCreate и onUpgrade. И у объекта полученного класса вызывается метод getWritableDastabase() для  получения объекта SQLiteDatabase, после окончания работы с БД необходимо разорвать подключение, вызвав у нашего объекта метод close(). Работая с БД используются ее стандартные методы такие как insert(), query(), rawquery(), update(),  delete(). Запрос данных методом query() выдает объект класса Cursor. В методе onCreate нашего класса наследника реализовываем заполнение нашей БД — метод execSQL. Метод query() имеет несколько параметров:
 columns – список запрашиваемых полей
selection – строка условия WHERE . В selection можно использовать знаки ? , которые будут заменены значениями из selectionArgs
selectionArgs – массив аргументов для selection.
groupBy — группировка
having – условия выборки, агрегатные функции
orderBy — сортировка
limit – строковый параметр, сколько строк пропустить и сколько вывести, формат:  [offset], rows
distinct – это boolean-параметр удаления дубликатов.
Для объединенного запроса из двух таблиц используется inner join c условием.
Чтобы была возможность откатить изменения, если данные прошли не полностью, используются транзакции. К примеру, транзакции незаменимы в методе обновления версии  onUpgrate() для БД. Для базы данных используются методы открытия соединения, успешного завершения и закрытия соединения — соответственно: beginTransaction(), setTransactionSuccessful(), endTransasction().  Рекомендуется помещать транзакции в блок try{}, завешая транзакцию в finally.

Советы Андроид-программисту

Советы Андроид-программисту
1. Все кажущееся сложным стараться разбивать на простые составные части.
2. Не лениться писать даже для себя комментарии в коде — со временем все забывается, а еще это поможет и другим разобраться в вашем коде.
3. Очень удобно использовать логи с метками для отладки программы, но в окончательном варианте программы их лучше удалить чтобы не было лишней утечки памяти на устройстве.
4.Программировать каждый день и не отвлекаться на посторонние дела.
5. Начинать следует всегда с простых вещей,  а только потом лезть в дебри.
6. Отладка программы всегда должна проводиться на реальном устройстве, отладки на эмуляторе не достаточно — очень часто программа работает по-разному, да и с эмулятором заметно медленнее.
7. Для элементов экрана использовать от плотности не зависимые единицы размерности dp , а для текта соответствующие единицы sp — чтобы приложение выглядело одинаково хорошо на всех экранах.
8.Для многокомпанентных приложений лучше сделать два вида экрана  - один для портретной ориентации, другой для горизонтальной.
9. Все названия в приложении лучше хранить в строковых ресурсах- в дальнейшем будет легко сделать программу
10.Участки кода, которые могут привести к сбоям программы надо помещать в блоки try.
11. Ориентироваться лучше на новое поколение Для совместимости с прошлыми поколениями Андроид-устройств  используйте специальные jar-библиотеки где это возможно.
12. Названия объектам класса лучше давать такие же как у самого класса с небольшим префиксом (напр. aButton).
13.Для хранения небольшого набора данных хорошо использовать Preferences, а для большого набора связных данных базу данных SQLite.
14.Чтобы приложение не зависало лишний раз не стоит грузить основной поток приложения отвечающий за экран и взаимодействие с пользователем, поэтому все сложные длительные операции необходимо выполнять в отдельном потоке для этого используя  специальный класс AsyncTask.
15.Ошибки в программе могут обнаружиться не только на этапе компилляции программы, но и в ходе ее работы — это надо учитывать и проверять программу на исключительные ситуации.

Подборка книг по Google Android

Подборка книг по Google Android

  1. Лорен Дэрси, Шейн Кондер — Android за 24 часа. Программирование приложений под операционную систему Google — 2011 — Книга содержит 24 простых урока, подойдет для начинающего.На протяжении книги шаг за шагом, урок за уроком создается и совершенствуется приложение-викторина «Been where, done what» c поддержкой сети и геолокационных сервисов (LBS, Location-Based Service), дополненное социальными функциями. Read the rest of this entry
 Page 1 of 1  1