Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Разработка мобильных приложений в среде Android Studio. Учебное пособие
.pdf
6.1. Создание RecyclerView
91
Данная функция вызывается системой каждый раз при создании но-
вого элемента. Если прокрутить список вниз, а потом вернуть вверх, эта
функция вызвана не будет, так как элемент был создан при первом появлении в области видимости и закеширован.
6. View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_item, parent, false);
Связывает макет элемента списка с View-элементом.
7. MyViewHolder vh = new MyViewHolder(v);
Создает объект класса MyViewHolder, в конструкторе которого со-
здаются все view-элементы и устанавливаются необходимые «слушатели».
8. public void onBindViewHolder(MyViewHolder holder, int position)
Данная функция вызывается после onCreateViewHolder() и наполняет
данными каждый элемент списка.
9. holder.mTextView.setText(mDataset.get(position));
В представленной строке view-элементам переданного ViewHolder
присваиваются данные, соответствующие переданной как входной параметр позиции. В примере данные получают из списка строк.
10. public int getItemCount()
Возвращает число (количество элементов списка). В примере данное
количество равно количеству элементов в mDataset.
После создания адаптера необходимо его применить к RecyclerView.
Таким образом, в классе Activity создаем поле:
private RecyclerView.Adapter mAdapter;
и присваиваем адаптер RecyclerView:
mRecyclerView.setAdapter(mAdapter);

6. Списки в мобильных приложениях
92
В текущем примере кода класса адаптера присутствует существенная
ошибка – адаптер не инициализирован. Для инициализации адаптера в конкретном примере необходим список строк, которые будут получать из ресурсов.
Первое – необходимо создать массив строк в файле strings.xml.
<string-array name="recycler_data">
<item>My string 1</item>
<item>My string 2</item>
<item>My string 3</item>
</string-array>
Второе – «прочитать» массив строк в Activity
String[] myString = getResources().getStringArray(R.array.recycler_data);
где из Activity получают класс ресурсов (getResources()), который отвечает
за все манипуляции с ресурсами, не только строковыми, но и с изображениями (drawable) и другими типами ресурсов. Далее по индексу
(R.array.recycler_data) происходит поиск массива и присвоение его массиву
типа String.
Третье – преобразование массива строк в список.
List<String> recyclerData = Arrays.asList(myString);
где Arrays.asList() – стандартная функция языка java для преобразования
массива в список.
Далее инициализируем адаптер созданным списком:
mAdapter = new MyRecyclerViewAdapter(recyclerData);
На данном этапе создание списка можно считать законченным. Результат правильно выполненных выше действий в виде экрана приложения
представлен на рис. 28.

6.2. Загрузка данных в RecyclerView
93
Рис. 28. Экран приложения со списком RecyclerView
6.2. Загрузка данных в RecyclerView
В подразд. 6.1 был рассмотрен способ заполнения списка данными из
ресурсов, в подразд. 5.1, 5.2 – загрузка с парсингом JSON-файла. Далее
рассмотрим объединение данных действий.
Список, содержащий данные для RecyclerView, необходимо определить как глобальный и проинициализировать. В результате чего его размер
будет равен 0:
private List<String> recyclerData = new ArrayList<>();
Далее следует инициализировать адаптер созданным списком и присвоить адаптер RecyclerView:
mAdapter = new MyRecyclerViewAdapter(recyclerData);
mRecyclerView.setAdapter(mAdapter);

6. Списки в мобильных приложениях
94
После необходимо модернизировать класс AsyncTask, созданный в
подразд. 4.1:
class MyAsyncTask extends AsyncTask<String, Integer, List<String>> {
protected List<String> doInBackground(String... arg) {
String myString = arg[0];
return myString;
}
protected void onPostExecute(List<String> fruitList) {
}
}
В представленном выше коде программы изменен третий параметр
класса со String на List<String>. Данный класс должен выполнять функцию
загрузки данных в RecyclerView, поэтому в его методе doInBackground
должно происходить формирование этого списка, а в методе onPostExecute
– передача его в адаптер. Для этого тип выходного значения doInBack-
ground и входного onPostExecute должен совпадать с типом списка в RecyclerView, как и третий тип AsyncTask.
Далее нужно представить логику загрузки данных в методе
doInBackground с использованием любого описанного ранее вида заполнения списка. Предположим, были загружены данные в формате JSON и преобразованы к типу Fruits, как показано в подразд. 5.2. Потом следует получить созданный список, дописав в классе Fruits метод getFruits, который
возвращает приватное поле List<String> fruits:
public List<String> getFruits() {
return fruits;
}
Таким образом, метод doInBackground примет вид:
protected List<String> doInBackground(String... arg) {
/*downloading json см. ЛР 5*/

6.2. Загрузка данных в RecyclerView
95
Gson gson = new Gson();
Fruits fruitItems = gson.fromJson(response.toString(), Fruits.class);
return fruitItems.getFruits();
}
Далее изменим логику работы метода onPostExecute:
protected void onPostExecute(List<String> fruitList) {
recyclerData.clear();
recyclerData.addAll(fruitList);
mAdapter.notifyDataSetChanged();
}
где
1) recyclerData.clear() предположим, что список заполняется не пер-
вый раз, в котором уже хранятся данные. Для удаления старых данных используется метод clear(), который удаляет все элементы.
2) recyclerData.addAll(fruitList) добавление новых данных в список.
Метод addAll копирует все элементы поданного ему на вход списка.
3) mAdapter.notifyDataSetChanged() метод уведомляет RecyclerView о
том, что содержащиеся в нем данные изменились и ему необходимо отобразить новые. Данный метод следует использовать, если изменяется весь
список. RecyclerView содержит методы для уведомления об изменении
(удалении, перемещении) одного элемента, изменения порядка следования
элементов:
3.1. notifyItemChanged(int)
3.2. notifyItemInserted(int)
3.3. notifyItemRemoved(int)
3.4. notifyItemRangeChanged(int, int)
3.5. notifyItemRangeInserted(int, int)
3.6. notifyItemRangeRemoved(int, int)
Такие узконаправленные методы действуют быстрее и экономичнее,
поэтому их использование предпочтительнее в любом удобном случае.
Для загрузки данных по адресу сайта, его нужно передать в Async-
Task. Тип передаваемого параметра должен соответствовать первому типу
AsyncTask. В примере данная строка, т.е. вызов загрузки данных с переда-
чей параметра выглядит следующим образом:

6. Списки в мобильных приложениях
96
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute("https://developer.android.com/");
6.3. Обновление списка
Загрузка данных в список требует обновления информации.
Для выполнения действий по «свайпу» сверху используется SwipeRefreshLayout [44], который считывает жест верхнего «свайпа» и уведомляет
о нем разработчика. Для его использования необходимо выполнить несколько шагов:
1. Добавить SwipeRefreshLayout в макет приложения. Он не отображается в списке элементов, потому все действия с ним нужно выполнять в
текстовом режиме. Так как это разновидность Layout, он должен содержать
в себе обновляемый элемент, в данном случае RecyclerView. Если этого не
сделать, уведомление о «свайпе» не придет. Этот элемент не требует какихлибо особых параметров, достаточно указать идентификатор, высоту и ширину. После добавления этого элемента код макета будет выглядеть следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/mySwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/recycler_view_item" />

Контрольные вопросы
97
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>
2. Следующий шаг – определение SwipeRefreshLayout в java-классе.
Обеспечивается стандартным способом с использованием метода
findViewById(), объект SwipeRefreshLayout делают глобальным для возможности обращения к нему из «слушателя» «свайпа», рассмотренного на
следующем шаге. В результате получим следующую строку:
private SwipeRefreshLayout mySwipeRefreshLayout;
mySwipeRefreshLayout = findViewById(R.id.mySwipeRefreshLayout);
3. Далее следует добавить объекту «слушатель» «свайпа» – onRefreshListener с методом onRefresh():
mySwipeRefreshLayout.setOnRefreshListener(new
SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mySwipeRefreshLayout.setRefreshing(false);
}
});
«Слушатель» обязательно должен содержать вызов функции
setRefreshing, для того чтобы убрать визуальное отображение индикатора
обновления. Принимаемый параметр имеет тип Boolean, где false означает
скрыть индикатор, true – показать.
На этом создание функции обновления списка можно считать законченным. Если нужно обновить данные в RecyclerView, в слушатель добавляется метод обновления данных или, например, вызов AsyncTask как было
показано ранее.
Контрольные вопросы
1. Способы организации списка в Android.
2. Различия между ListView и RecyclerView.
3. Особенности RecyclerView.

6. Списки в мобильных приложениях
98
4. Основные методы RecyclerView.
5. Шаги создания RecyclerView.
6. Что такое адаптер?
7. Создание адаптера.
8. Основные методы адаптера.
9. Загрузка данных в RecyclerView.
10. Что такое SwipeRefreshLayout?
11. Шаги реализации SwipeRefreshLayout.

99
7. БАЗА ДАННЫХ В ANDROID
В большинстве мобильных приложений в процессе работы приложения возникает необходимость где-то хранить большой объем данных, и самым подходящим вариантом являются базы данных (БД). В системе Android используется БД SQLite.
SQLite является бесплатной библиотекой, которая реализует автономные базы данных, не нуждающиеся в серверах и не требовательные к
ресурсам, компактные и надежные. Работа с БД SQLite выполняется посредством команд языка SQL. SQLite читает и пишет данные в обычные
файлы на диске. Полная база данных SQL с несколькими таблицами,
индексами, триггерами и представлениями компактно хранится в одном
файле.
7.1. Создание базы данных
Первым шагом при работе с БД является её создание и обновление на
более новую версию. Данные действия в системе Android реализуются с
использованием класса SQLiteOpenHelper [45]. Необходимо создать класснаследник SQLiteOpenHelper (в представленном ниже примере – класс
DBHelper), который может находиться как в одном файле с Activity, так и в
отдельном.
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(@androidx.annotation.Nullable Context context,
@androidx.annotation.Nullable String name,
@androidx.annotation.Nullable SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public DBHelper(@androidx.annotation.Nullable Context context,
@androidx.annotation.Nullable String name,
@androidx.annotation.Nullable SQLiteDatabase.CursorFactory factory,
int version, @androidx.annotation.Nullable DatabaseErrorHandler er-
rorHandler) {
super(context, name, factory, version, errorHandler);
}

7. База данных в Android
100
public DBHelper(@androidx.annotation.Nullable Context context,
@androidx.annotation.Nullable String name, int version,
@androidx.annotation.NonNull SQLiteDatabase.OpenParams openParams) {
super(context, name, version, openParams);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
В классе DBHelper имеются три вида конструкторов и два метода on-
Create и onUpgrade. В данном учебном пособии будет использоваться пер-
вый конструктор, входными параметрами которого являются контекст,
название БД, фабрика курсоров (в приведенных примерах не используется)
и версия БД. В методе onCreate должны содержаться скрипты создания
таблиц, в методе onUpgrade (вызывается при изменении версии БД) –
скрипты изменения таблиц.
Вторым шагом при работе с БД является создание таблиц в методе
onCreate() с использованием метода execSQL() [46], который выполняет переданный ему скрипт, например, для создания таблицы. Данный метод будет вызван только если БД не существует и ее необходимо создать. В
примере ниже приведен скрипт создания таблицы:
db.execSQL("create table mytable ("
+ "id integer primary key autoincrement,"
+ "field1 text,"
+ "field2 text" + ");");
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
