Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Разработка мобильных приложений в среде Android Studio. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
3.2. Альтернативные ресурсы
61
Рис. 20. Структура проекта с использованием альтернативных ресурсов
3. Работа с ресурсами
62
Рис. 21. Пример Activity с отображением View-элементов из ресурсов
Назначение ресурсов из кода программы, представленного выше примера выглядит следующим образом:
public class MainActivity extends AppCompatActivity {
TextView text1;
TextView text2;
ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
3.3. Добавление графических ресурсов
63
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
text1 = findViewById(R.id.textView); text2 = findViewById(R.id.textView3); img = findViewById(R.id.imageView);
img.setImageResource(R.drawable.img1);
text1.setText(R.string.app_string2); text2.setText(R.string.app_name); } }
Назначение ресурсов из файла разметки:
<ImageView android:id="@+id/imageView" android:src="@drawable/img1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.029" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
3.3. Добавление графических ресурсов
Существует огромное количество разных разрешений экранов, кото­рые группируются в несколько видов и для каждого рекомендуется хранить отдельное изображение. Такой массив изображений можно создавать вруч­ную, делая нужное количество изображений необходимого размера в сто­роннем редакторе, а можно воспользоваться инструментом Android Drawa- ble Importer. Данный инструмент не входит в основной комплект инстру­ментов среды. Его необходимо загрузить: в меню перейти File->Settings-
>Plugins->Browse Repositories… и в поисковой строке набрать «Android Drawable Importer», нажать кнопку Install и перезагрузить среду разработ- ки. Использовать его можно следующим образом.
3. Работа с ресурсами
64
1. Правой кнопкой нажать по папке drawables->New->Batch Drawable
Importer. Откроется следующее окно (рис. 22).
Рис. 22. Batch Drawable Importer
2. Нажать на кнопку «+» и выбрать файл (рис. 23).
Рис. 23. Создание изображений разного разрешения
Контрольные вопросы
65
Source-Resolution – разрешение, для которого изображение будет им-
портировано в оригинальном размере, Target-Resolution – в какие разреше­ния нужно преобразовать картинку, остальные параметры необязательны для изменения.
3. Нажать кнопку OK и среда разработки создаст папку drawables с суффиксом того разрешения, какого она содержит ресурса. Для каждого устройства система будет брать подходящий ей ресурс, ничего дополни­тельно устанавливать не нужно.
Контрольные вопросы
1. Что такое ресурсы в Android приложении?
2. Типы ресурсов.
3. Способы использования ресурсов.
4. Работа с ресурсами из кода приложения.
5. Работа с ресурсами в XML-файле.
6. Что такое альтернативные ресурсы?
7. Алгоритм добавления альтернативных ресурсов.
8. Типы квалификаторов.
9. Что такое Android Drawable Importer?
10. Использование Android Drawable Importer.
66
4. МНОГОПОТОЧНОСТЬ В ПРИЛОЖЕНИЯХ
Запуская приложение в Android, система создает новый процесс с од­ним потоком выполнения, таким образом, все компоненты одного прило­жения работают в одном процессе и потоке. Существуют механизмы орга­низации выполнения компонентов приложения в отдельных процессах и создание дополнительных потоков для любого процесса [29].
При запуске приложения система создает поток выполнения для при­ложения, который называется «главным». Данный поток отвечает за от­правку событий в соответствующие виджеты пользовательского интерфей­са, а также связь с компонентами из набора инструментов Android UI (ком­понентами из пакетов android.widget и android.view). Таким образом, он является так называемым потоком пользовательского интерфейса (UI-потоком).
Система не создает отдельного потока для каждого экземпляра ком­понента. Все компоненты, которые выполняются в одном процессе, созда­ют экземпляры в потоке пользовательского интерфейса, и системные вызо­вы каждого компонента отправляются из этого потока.
В ситуациях, когда приложение выполняет интенсивную работу в от­вет на действия пользователя, эта одиночная модель потока может показы­вать плохую производительность при не корректной реализации приложе­ния. Например, выполнение долговременных операций в потоке пользова­тельского интерфейса, таких как сетевой доступ или запросы к базе дан­ных, будет блокировать весь пользовательский интерфейс и с точки зрения пользователя приложение выглядит зависшим. При блокировке потока пользовательского интерфейса более нескольких секунд (в настоящее вре­мя около 5 секунд), пользователю отображается диалоговое окно «прило­жение не отвечает». После этого недовольный пользователь может выйти из вашего приложения и удалить его.
Кроме того, набор инструментов пользовательского интерфейса Android не является потокобезопасным. Поэтому вы не должны работать с пользовательским интерфейсом из рабочего потока, только из потока поль­зовательского интерфейса. Отсюда появляются правила однопоточной мо­дели Android:
- не блокировать поток пользовательского интерфейса;
4.1. AsyncTask
67
- не обращаться к набору инструментов пользовательского интер-
фейса Android из вне потока пользовательского интерфейса.
4.1. AsyncTask
Вследствие описанной выше однопоточной модели для динамично­сти пользовательского интерфейса приложений очень важно не блокиро­вать поток пользовательского интерфейса (UI-поток), поэтому необходимо создавать отдельные потоки («нити») для выполнения трудозатратных опе­раций.
Система предлагает несколько способов создания дополнительных потоков – это класс Thread (нити, которые позволяют только выполнить ка­кие-либо действия, но не имеют доступа к основному потоку) и AsyncTask (позволяет отправить в поток данные, обработать их и вывести в основную нить). AsyncTask наиболее удобен для выполнения действий в дополни­тельном потоке, требующих по завершению которых передать результат обработки в основную нить [30].
AsyncTask – интерфейс, содержащий функции для передачи входных значений в дополнительный поток, обработки и вывода в основной поток. Для его использования обязательно создание класса-наследника от Async­Task. Он может находиться как внутри класса Activity, так и в отдельном классе. При создании интерфейса определяются три типа параметра, ис­пользуемых в методах интерфейса, их использование описано ниже. Ин­терфейс содержит следующие функции:
1) onPreExecute() – вызывается в основном потоке. Не имеет входных и выходных параметров, используется для выполнения действий перед об­работкой задач в дополнительном потоке;
2) doInBackground() – вызывается сразу после onPreExecute(). Это и есть дополнительный поток, в котором выполняются основные действия. Имеет входной параметр первого из типов, указанных в описании класса. Данный параметр определяется со следующим синтаксисом:
protected String doInBackground(String... arg) { return null;}.
Это означает, что параметров, переданных в метод, может быть не­ограниченное количество. Доступ к ним можно легко получить, предста­вив, что параметр arg – массив, т.е. доступ к входным параметрам будет
4. Многопоточность в приложениях
68
происходить по индексу в массиве arg: arg[0], arg[1] и т.д. Метод имеет вы­ходной параметр третьего типа, указанного в списке параметров.
В процессе выполнения длительной обработки может понадобиться вывести промежуточный результат. Это можно сделать с помощью функ­ции publishProgress(). Входным параметром является переменная типа, ука- занного вторым при объявлении класса. При вызове данной функции авто­матически будет вызван метод onProgressUpdate();
3) onProgressUpdate() – метод вызывается в основном потоке сразу
после вызова publishProgress(). Имеет входной аргумент второго типа;
4) onPostExecute() – вызывается сразу после завершения выполнения всех действий в методе doInBackground() в основном потоке. Имеет вход­ной параметр третьего типа в списке параметров. Выходной параметр ме­тода doInBackground() является входным для onPostExecute(). Это своеоб­разный способ передачи данных из дополнительного потока в основной. После его вызова завершается выполнение всех операций в AsyncTask.
Запустить выполнение данного класса следует путем вызова метода
execute() от экземпляра класса с желаемым набором параметров.
Рассмотрим пример работы разработанного класса AsyncTask.
class MyAsyncTask extends AsyncTask<String, Integer, String> {
protected void onPreExecute(){ Log.i("MyAsyncTask", "PreExecute"); }
protected String doInBackground(String... arg) { String myString = arg[0]; publishProgress(50); Log.i("MyAsyncTask", "InBackground, input arg: " + arg[0]); return myString; }
protected void onProgressUpdate (Integer... values){ Log.i("MyAsyncTask", "Progress is " + values[0]); } protected void onPostExecute(String output) {
Контрольные вопросы
69
Log.i("MyAsyncTask", "Output string = " + output); } }
Вызвать представленный выше класс можно следующим образом:
MyAsyncTask myAsyncTask = new MyAsyncTask(); myAsyncTask.execute("InputString");
В примере представлен AsyncTask со входными параметрами String, Integer, String и всеми доступными методами. При запуске данного класса в «логах» можно увидеть следующую последовательность:
MyAsyncTask : PreExecute
MyAsyncTask : Progress is 50
MyAsyncTask : InBackground, input arg InputString
MyAsyncTask : Output string = InputString
Контрольные вопросы
1. Процессы и потоки в Android.
2. Поток пользовательского интерфейса.
3. Выполнений операций в UI потоке.
4. Правила однопоточной модели Android.
5. Метод организации многопоточности.
6. Что такое AsyncTask?
7. Основные методы AsyncTask.
8. Входные параметры AsyncTask.
9. Шаги использования AsyncTask.
70
5. РАБОТА С СЕТЬЮ
В настоящее время большинство Android-устройств имеют доступ к сети Интернет, тем самым обеспечивая возможность мобильным приложе­ниям взаимодействовать с ней: загружать файлы, авторизовываться и полу­чать информацию с внешних веб-сервисов и т.д. Разрабатывая приложения с таким функционалом, необходимо учитывать следующее [31]:
– трафик. Не всегда есть возможность работать по бесплатному Wi-Fi-соединению, а мобильный интернет всё еще дорогой, и об этом нуж­но помнить, потому что трафик – это деньги пользователя;
– лимит батарейки. Мобильные устройства необходимы пользовате­лю для каких-то повседневных дел, совещаний, прогулок, бизнеса, и когда батарейка садится в самый неподходящий момент;
– безопасность. Так как все-таки речь идет о мобильных клиентах, и данные распространяются по сети от клиента к серверу и обратно, то их необходимо защищать.
5.1. Загрузка данных с сайта
Любые действия, связанные с использованием сети Интернет, требу­ет указания разрешений в файле манифеста:
<uses-permission android:name="android.permission.INTERNET"/>
Получение данных с сайта в первую очередь требует определения от­куда будут получены данные, то есть его адрес. Адрес необходимо пред­ставить в экземпляре класса URL. Данный класс имеет много разных кон­структоров и методов, несущественных для текущей задачи [32]. Для теку­щей задачи достаточно создать экземпляр класса с конструктором для ини­циализации требующим строку, содержащую адрес сайта. Конструктор по требованиям компилятора обязательно должен быть заключен в блок обра­ботки ошибок.
String url = "https://developer.android.com";
URL url = null;
try {
url = new URL(url);
} catch (MalformedURLException e) {
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]