Академический Документы
Профессиональный Документы
Культура Документы
НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ (НИ ТГУ)
Научно-образовательный центр «Высшая ИТ школа»
КУРСОВАЯ РАБОТА
Руководитель
ассистент кафедры
программной инженерии
______________Л.С. Иванова
«_____»____________2022 г.
Выполнил
студент группы 971902
______________В.М. Бабак
Томск - 2022
РЕФЕРАТ
2
ОГЛАВЛЕНИЕ
Глоссарий............................................................................................................................4
Введение.............................................................................................................................5
1 Анализ требований.........................................................................................................6
3 Реализация.....................................................................................................................20
3.4 Навигация...............................................................................................................24
3.6 Календарь...............................................................................................................28
3.8 Списки.....................................................................................................................31
Заключение.......................................................................................................................35
Приложение A..................................................................................................................38
3
ГЛОССАРИЙ
4
ВВЕДЕНИЕ
5
1 Анализ требований
6
17. Внести в журнал информацию о температурах, используемых при обработке.
Количество принятых изделий, а также отправку в лабораторию.
7
1.2 Функциональные требования
8
Рисунок 1.2 – Просмотр журнала ТП для термиста
При создании садки (рисунок 1.4), пользователь должен добавить в нее как
минимум одну номенклатуру и фотографию. Уже созданную номенклатуру можно
редактировать или удалить. Фотографию можно только удалить. Для сохранения
номенклатуры пользователю необходимо выбрать партию из списка, а при наличии
бракованных деталей становится обязательным указание контролера.
9
Рисунок 1.4 – Добавление, редактирование и удаление номенклатуры в садке
10
партий
5. Отображает экран со списком партий
6. Выбирает партию
7. Передает выбранную партию на экран
создания номенклатуры
8. Отображает экран создания
номенклатуры
9. Вводит общее количество деталей
10. Нажимает кнопку «Сохранить»
11. Проверяет наличие выбранной партии
12. Проверяет, что общее количество
деталей больше нуля
13. Передает созданную номенклатуру на
экран создания садки
14. Отображает экран создания садки
15. Нажимает на кнопку добавления
фотографии
16. Отображает диалоговое окно с
выбором источника для добавления
фотографии
17. Выбирает добавить фотографию из
галереи
18. Открывает экран выбора фотографии
из галереи
19. Нажимает на фотографию
20. Передает фотографию на экран
создания садки
21. Открывает экран создания садки
22. Конвертирует фотографию в Base64
23. Нажимает кнопку «Сохранить»
24. Проверяет наличие хотя бы одной
фотографии и одной номенклатуры
25. Проверяет, что количество фотографий
не более 5
11
26. Отправляет садку на сервер
27. Отображает результат сохранения
садки
Расширения
Расширение шага 9. Пользователь вводит общее количество деталей и количество
дефектных деталей, которое больше нуля
9. Нажимает на поле Контролер ОТК
9.1. Отправляет запрос на получение
списка контролеров
9.2. Открывает экран со списком
контролеров ОТК
9.3. Нажимает на контролера ОТК
9.4. Отправляет контролера ОТК на экран
создания номенклатуры
9.5. Отображает экран создания
номенклатуры
Расширение шага 12. Общее количество деталей не больше нуля
12.1 Отображает ошибку в поле общего
количества деталей
12.2 Вводит новое значение в поле общего
количества деталей
12.3 Нажимает кнопку «Сохранить»
12.4 Проверяет новое значение поля.
Расширение может повторяться до тех пор,
пока пользователь не введет корректные
данные
Альтернативы
Альтернатива 5. Пользователь хочет воспользоваться поиском партий
5.1 Пользователь вводит нужное слово в
поле для поиска
5.2 Отсылает запрос на сервер для
получения отсортированного списка
5.3 Отображает отсортированный список
партий
12
5.4 Выбирает партию
Сценарий продолжается с шага 7 основного сценария
Альтернатива 17. Пользователь выбирает сделать фотографию с помощью камеры
17.1 Открывает приложение для съемки,
установленное на телефоне пользователя
по умолчанию
17.2 Делает снимок
17.3 Передает фотографию на экран
создания садки
Сценарий продолжается с 21 шага основного сценария
13
1.4 Модель предметной области
14
2 Анализ инструментов и выбор архитектуры приложения
15
4. Структурированный параллелизм – сопрограммы Kotlin упрощают асинхронное
программирование, делая обычные задачи, такие как сетевые вызовы и
обновления базы данных, простыми и эффективными.
5. Приоритетность – в мае 2017 года компания Google опубликовала новость о
том, что инструменты языка Kotlin будут по умолчанию включены в Android
Studio, которая является официальным инструментом разработки OC Android. В
2019 году на Google I/O объявили, что Kotlin стал приоритетным языком
программирования в разработке под Android.
16
4) App. Модуль, который является основной точкой входа в приложение, в нем
содержатся вспомогательные классы для внедрения зависимостей в проект.
17
Рисунок 2.1 – Архитектура приложения
В конечном итоге было принято решение реализовать описанную архитектуру
следующим образом (Рисунок 2.2):
18
2.5 Пакеты приложения
19
3 Реализация
20
11. Gson [14] Позволяет конвертировать объекты
JSON в Kotlin-объекты и наоборот
21
Для отправки запроса на сервер сначала был создан объект класса Retrofit с
помощью Retrofit.Builder (Листинг 3.1).
Листинг 3.1 – Создание объекта класса Retrofit
При вызове метода объект класса Retrofit отправляет запрос на сервер и ожидает
получения ответа. Если код ответа равен 200, то полученный JSON-файл преобразуется в
возвращаемый класс вызванного метода, при помощи библиотеки GSON [14].
Для большинства запросов необходим токен, который получает приложение при
аутентификации пользователя. Библиотека OkHttp предоставляет интерфейс Interceptor,
22
который изменяет и сокращает код исходящих запросов. В проекте используется класс
AuthenticationInterceptor, который запрашивает токен из локальной базы данных и
вставляет его в заголовок запроса. Это помогает избежать прописывания токена для
каждого нового запроса.
Бывают ситуации, что время жизни токена истекло и его нужно обновить. За это
отвечает класс RefreshTokenAuthenticator, который отправляет запрос на получение нового
токена, а затем сохраняет его в локальной базе данных (Листинг 3.4).
EventBus.getDefault().post(RefreshTokenInvalidEvent())
return null
}
dataStoreRepository.saveNewAccessToken(newAccessToken
val newRequest = response.request.newBuilder()
23
Для сохранения данных используется функция updateDataAsync(), которая
обновляет значения. Чтобы извлечь данные, используется функция readData(), которая
возвращает Flowable, после этого вызывается функция firstOrError(), чтобы получить
результат типа Single.
3.4 Навигация
24
Рисунок 3.2 – Карта переходов между экранами
25
Листинг 3.6 – Граф навигации на примере экранов с садкой и номенклатурой
<navigation
xmlns:android="http://schemas.android.com/apk/res/
android"
xmlns:app="http://schemas.android.com/apk/res-
auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/app_navigation">
<fragment
android:id="@+id/nomenclatureFragment"
android:name="ai.ntr.kamaz.presentation
.nomenclature.NomenclatureFragment"
android:label="@string/fragment_nomenclature_label"
tools:layout="@layout/fragment_nomenclature"
<argument
android:name="nomenclature"
app:argType="ai.ntr.kamaz.domain.entity
.SchichtNomenclature"
app:nullable="true" />
<argument
android:name="oldNomenclatureId"
app:argType="integer"/>
</fragment>
<fragment
android:id="@+id/schichtFragment"
android:name="ai.ntr.kamaz.presentation
.schicht.SchichtFragment"
android:label="@string/fragment_new_schicht_label"
tools:layout="@layout/fragment_schicht">
<argument
android:name="id"
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_schichtFragment_to_
nomenclatureFragment"
26
Для того чтобы добавить Navigation Drawer в свой проект, в xml-файл главной
активности был добавлен DrawerLayout, содержащий в себе AppBar, компонент для
отображения контента и NavigationView. В классе MainActivity необходимо провести
инициализацию компонентов: NavController, DrawerLayout, NavigationView, а также
AppBarConfiguration, который используется для управления поведением кнопок в меню.
NavigationView в разметке xml-файла было присвоено заранее созданное меню
(Листинг 3.7), а также добавлен слушатель нажатия по элементам, который осуществляет
навигацию на нужные экраны.
<menu
xmlns:android="http://schemas.android.com/apk/res/andr
oid"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:id="@+id/menu_top">
<item
android:id="@+id/journalFragment"
android:icon="@drawable/journal"
android:title="@string/journal_tp"
android:iconTint="@color/white"/>
<item
android:id="@+id/batchesFragment"
android:icon="@drawable/products"
android:title="@string/products"
</group>
<group android:id="@+id/menu_bottom">
<item
android:id="@+id/loginFragment"
android:icon="@drawable/exit"
В данном проекте необходимо было отключить возможность открытия меню на
экране авторизации и восстановления пароля. Это было сделано при помощи добавления к
navController слушателя смены экранов (Листинг 3.8).
Листинг 3.8 – Блокировка бокового меню и скрытие AppBar
if (destination.id == R.id.loginFragment ||
destination.id == R.id.resetPasswordFragment) {
27
Рисунок 3.3 – Скриншот бокового меню
3.6 Календарь
28
Листинг 3.9 – Установка максимальной и минимальной даты
29
3.7 Добавление фотографий
30
Рисунок 3.5 – Выбор источника добавления фотографии.
3.8 Списки
31
Объект адаптера необходимо создать и инициализировать во фрагменте садки, а
затем назначить нужному RecyclerView. Здесь же происходит инициализация слушателя
нажатия кнопки у элемента
if (responseCount(response) >
MAX_AMOUNT_OF_REFRESH_TRIES) {
EventBus.getDefault().post(RefreshTokenInvalidEvent())
return null
}
val refreshToken = getRefreshToken()
val newAccessToken = try {
getNewAccessToken(refreshToken)
} catch (e: Throwable) {
32
В MainViewModel был объявлен и аннотирован метод подписки на событие. В
данном случае, необходимо было удалить данные пользователя в локальном хранилище и
выйти из аккаунта пользователя на экран авторизации (Листинг 3.12).
@Subscribe
fun onRefreshTokenInvalid(event:
RefreshTokenInvalidEvent) {
clearUserDataUseCase.invoke(ClearUserDataParams())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result ->
result.onSuccess {
_name.postValue("")
_userIsNotSignedIn.postValue(
Также необходимо зарегистрировать и отменить регистрацию событий с учетом
жизненного цикла активности. В MainViewModel в функции init() происходит
регистрация, а в функции onCleared() ее отмена.
33
В репозитории садки есть метод, возвращающий информацию о садке по ее id, с
типом Single<SchichtDetails>. Этот метод вызывается в юзкейсе GetSchichtByIdUseCase.
При получении успешного значения, оно оборачивается в kotlin.Result.success(), а при
получении ошибки в kotlin.Result.failure().
Листинг 3.13 – Юзкейс получения садки
BaseUseCase<Single<Result<SchichtDetails>>,
GetSchichtByIdParams> {
override fun invoke(params: GetSchichtByIdParams
Single<Result<SchichtDetails>> =
schichtRepository.getSchicht(params.id
Result.success(it)
34
getSchichtByIdUseCase.invoke(GetSchichtByIdParams(id))
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result ->
result
.onSuccess { schichtInfo ->
_schicht.value = schichtInfo
_schicht.value?.schichtNomenclature?.let {
_nomenclatureList.value =
it as
ArrayList<SchichtNomenclature>
}
_schicht.value?.photos?.let {
_photoList.value = it as
ArrayList<SchichtPhoto>
}
_schichtSuccess.call()
_isFinishedLoading.call()
}
.onFailure {
_schichtError.value = when (it
is ErrorEntity.ServiceUnavailable
-> {
BaseError.ErrorNetwork
}
else -> {
SchichtFragment.Companion.GetSchichtError
}
}
35
ЗАКЛЮЧЕНИЕ
36
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ЛИТЕРАТУРЫ
37
16. Чистая архитектура // Р. С. Мартин – [Б. м.], 2012. URL:
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
38
ПРИЛОЖЕНИЕ A
39
Рисунок А.5 – Календарь Рисунок А.6 – Контроль закалки
40
Рисунок А.8 – Боковое меню Рисунок А.10 – Садка на этапе закалка
41
Рисунок А.12 – Этапы ТП садки
42
43