Евгений Сенько - Программирование приложений для мобильных устройств под управлением Android. Часть 2
- Название:Программирование приложений для мобильных устройств под управлением Android. Часть 2
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:9785448566073
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Евгений Сенько - Программирование приложений для мобильных устройств под управлением Android. Часть 2 краткое содержание
Программирование приложений для мобильных устройств под управлением Android. Часть 2 - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
У этой проблемы есть одно на вид очевидное, но, в конечном счете, неправильное решение – перейти к «слушателю» кнопки «Load Icon» и просто создать новый поток, который будет загружать битовый массив и затем выведет его на экран. Пример такой реализации – приложение Threadingsimple, вот его код.

«Слушатель» кнопки «Load Icon» вызывает метод loadIcon (), который показан чуть ниже. Этот код создает новый поток, который занимает время, загружая битовый массив. И затем пытается установить изображение в image view, который является частью лейаута.

Теперь, если запустить приложение и нажать кнопку «Load Icon», а затем сразу нажать «Other Button», видно, что есть реакция на «Other Button» и её нажатие не блокируется. Это хорошо, есть прогресс. Однако появилась большая проблема, через несколько секунд приложение рухнуло.

Если исследовать журнал logcat, мы увидим, что есть сообщение о том, что только тот поток, в котором создана иерархия вьюшек, может манипулировать своими вьюшками.

Это означает, что новый поток, который мы создали, чтобы загрузить битовый массив, может сделать эту работу, но он не сможет сделать последний шаг и вывести получившееся изображение на дисплей.
И так, какой же поток на самом деле создал иерархию вьюшек этого приложения? У всех Android приложений есть основной поток, который также называют UI thread – потоком пользовательского интерфейса. Все компоненты приложения, которые работают в одном и том же процессе, запущенном по умолчанию, используют тот же поток – UI thread. Все методы жизненного цикла: OnCreate, OnStart и т.д., работают в основном потоке. И, кроме того, сам инструментарий пользовательского интерфейса не ориентирован на многопотоковое исполнение. Все это означает, что, если вы заблокируете UI-поток любой продолжительной работой, это воспрепятствует реакции приложения на другие манипуляции пользователя. Следовательно, долго выполняющиеся операции должны быть помещены в фоновые потоки. Однако, вместе с этим, мы не сможем получить доступ к инструментарию пользовательского интерфейса от потока, не принадлежащего UI tread. Таким образом, мы должны делать длительную работу в фоновом потоке, но когда эта работа сделана, мы должны сделать обновление пользовательского интерфейса в потоке UI.
И Android на самом деле дает нам набор средств сделать это. В частности Android обеспечивает несколько методов, которые гарантированно будут работать в потоке пользовательского интерфейса. Два из них – это метод post класса View и runOnUiThread класса Activity. Оба этих метода получают параметр Runnable, содержащий код, который, например, обновляет экран в наших недавних примерах. Таким образом, если мы используем эти методы, мы могли бы загрузить битовый массив в фоновом потоке, и когда эта операция завершится, мы использовали бы один из этих методов, чтобы выполнить Runnable, который и выведет изображение на экран.
Давайте рассмотрим, как это реализуется в коде. Откроем основную Activity этого приложения и перейдем прямо к методу loadIcon, который вызывается, когда пользователь нажимает кнопку «Load Icon». Как и в предыдущем примере, этот код создает новый поток и затем загружает битовый массив. Но после загрузки данных, теперь происходит вызов view.post, запускающий новый Runnable, код которого и вызывает метод setImageBitmap, чтобы установить загруженное изображение в соответствующий imageView.

Следующий класс, обеспечивающий поточную обработку, это класс AsyncTask. Он обеспечивает правильное и простое использование потока пользовательского интерфейса. Этот класс служит общей основой для управления задачами, которые, как в наших предыдущих примерах, включают операции, которые должны выполняться в фоновом потоке, а их результат публикуется в UI потоке. Основой использования AsyncTask является то, что работа разделена между фоновым потоком и потоком UI. Фоновый поток выполняет длительную операцию и может дополнительно сообщать о ее прогрессе. Поток пользовательского интерфейса, с другой стороны, ответственен за начальную настройку длительно выполняемой операции, за публикацию промежуточной информации о прогрессе и за завершение операции после того, как фоновый поток сделал свою работу.
AsyncTask – универсальный класс. Он определяется тремя основными параметрами: params, progress, и result. Params – тип параметров, которые отправляются в AsyncTask при выполнении. Progress – тип любых единиц прогресса, публикуемого в процессе выполнения фоновой операции. Result – тип результата фонового вычисления.
Во время выполнения AsyncTask проходит через четыре шага. Во-первых, onPreExecute () – метод вызывается в потоке UI до начала работы фонового потока.
Сразу же после него запускается doInBackground (Params…) и выполняет вычисления в фоновом режиме. Сюда же передаются параметры. И этот же метод возвращает в последний шаг результат типа Result.
Во время работы doInBackground может дополнительно вызвать метод publishProgress (Progress…) с перечнем переменных, который обеспечит некоторую индикацию прогресса длительного процесса. А переданные переменные используются в UI потоке при помощи метода onProgressUpdate (Progress…), который запускается в потоке пользовательского интерфейса после вызова publishProgress.
И последний шаг, onPostExecute (Result) вызывается в UI потоке после окончания фоновых вычислений с результатом, возвращенным как его параметр.
Давайте рассмотрим версию нашего приложения загрузки картинки, реализованного с AsyncTask. Если мы запустим приложение, то увидим, что оно выглядит подобно предыдущим примерам, но здесь добавлен новый элемент интерфейса – индикатор выполнения, который показывает, какое количество работы по загрузке изображения уже выполнено.
После нажатия кнопки «Load Icon» появится маленький индикатор выполнения и начнет медленно заполняться. После нажатия второй кнопки раскроется знакомый текст – кнопка «Other Button» работает. И наконец, на экране появится изображение.

А теперь рассмотрим исходный код этого приложения. Откроем основную Activity.
Читать дальшеИнтервал:
Закладка: