Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Разработка мобильных приложений в среде Android Studio. Учебное пособие
.pdf
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 – интерфейс, содержащий функции для передачи входных
значений в дополнительный поток, обработки и вывода в основной поток.
Для его использования обязательно создание класса-наследника от AsyncTask. Он может находиться как внутри класса 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) {
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
