Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Котлин4.docx
Скачиваний:
0
Добавлен:
12.04.2025
Размер:
866.37 Кб
Скачать

ГУАП

КАФЕДРА № 42

ОТЧЕТ ЗАЩИЩЕН С ОЦЕНКОЙ

ПРЕПОДАВАТЕЛЬ

Доцент, канд. техн. наук

В.А. Ушаков

должность, уч. степень, звание

подпись, дата

инициалы, фамилия

ОТЧЕТ О ПРАКТИЧЕСКОЙ РАБОТЕ №4

СУБД И ИСПОЛЬЗОВАНИЕ СЕТЕВЫХ СЕРВИСОВ

по курсу:

Разработка мобильных приложений. Разработка мобильных приложений на Kotlin

РАБОТУ ВЫПОЛНИЛ

СТУДЕНТ гр. №

4116

подпись, дата

инициалы, фамилия

Санкт-Петербург 2024

Цель работы: выполнить проектирование и разработку мобильного приложения под ОС Android на языке программирования высокого уровня Kotlin.

Вариант 10: Класс «Таксопарк»

Ход работы:

В проект из прошлой практической работы были подключены необходимые зависимости и установлен плагин (Листинг 1, 2).

Листинг 1 - Подключение зависимостей

implementation("androidx.room:room-ktx:2.5.0")

implementation("androidx.room:room-runtime:2.5.0")

kapt("androidx.room:room-compiler:2.5.0")

implementation ("androidx.recyclerview:recyclerview:1.2.1")

Листинг 2 – Установка плагина

id("kotlin-kapt")

Созданы макеты страниц для заказа такси, отображения всех поездок в RecyclerView и макет элемента списка (Рисунок 1 - 3).

Рисунок 1 – Макет страницы заказа

Рисунок 2 – Макет RecyclerView

Рисунок 3 – Макет элемента списка

На странице заказа пользователю предоставляются 3 поля для заполнения: количество пассажиров, откуда и куда будет поездка. Под полями расположены кнопки для заказа, при нажатии данные заносятся в БД, и для просмотра всех поездок, при нажатии происходит переход на страницу с RecyclerView. Вид страницы в приложении представлен на рисунке 4.

Рисунок 4 – Страница для заказа

На рисунках 5 и 6 представлен процесс ввода числовых и текстовых данных.

Рисунок 5 – Числовой ввод

Рисунок 6 – Текстовый ввод

После нажатия кнопки “Заказать” происходит занесение данных в БД и высвечивается уведомление об успешном добавлении данных (Рисунок 7).

Рисунок 7 – Успешное добавление данных

На странице со всеми поездками находится RecyclerView, в котором отображаются все поездки из БД (Рисунок 8).

Рисунок 8 – Страница со всеми поездками

Рядом с каждой поездкой отображен значок удаления, при нажатии на него появляется кнопка для удаления поездки (Рисунок 9, 10).

Рисунок 9 – Кнопка для удаления

Рисунок 10 – Список поездок после удаления

Была создана БД используя библиотеку Room (Листинг 3).

Листинг 3 – Создание БД

@Database(

version = 1,

entities = [

RidesDbEntity::class

]

)

abstract class AppDatabase : RoomDatabase() {

abstract fun getRidesDao(): RidesDAO

}

Реализована модель данных поездки (Листинг 4).

Листинг 4 – Модель данных поездки

data class Ride(

val passengers: Int,

val start: String,

val destination: String

)

Создана таблица “rides” для хранения поездок в БД (Листинг 5).

Листинг 5 – Создание таблицы

@Entity(

tableName = "rides",

indices = [Index("id")],

)

data class RidesDbEntity(

@PrimaryKey(autoGenerate = true) val id: Long,

@ColumnInfo(name = "Passengers") val passengers: Int,

@ColumnInfo(name = "Start") val start: String,

@ColumnInfo(name = "Destination") val destination: String

)

Для взаимодействия с БД разработан DAO интерфейс (Листинг 6).

Листинг 6 – DAO интерфейс

@Dao

interface RidesDAO {

@Insert(entity = RidesDbEntity::class)

fun insertRideData(ride: RidesDbEntity)

@Query("SELECT rides.id, passengers, start, destination FROM rides\n")

fun getAllRideData(): List<RideDataTuple>

@Query("DELETE FROM rides WHERE id = :rideId")

fun deleteRideDataById(rideId: Long)

}

Разработаны функции для взаимодействия с БД (Листинг 7).

Листинг 7 – Функции для работы с БД

class RidesRepository(private val ridesDAO: RidesDAO) {

suspend fun insertNewRideData(ridesDbEntity: RidesDbEntity) {

withContext(Dispatchers.IO) {

ridesDAO.insertRideData(ridesDbEntity)

}

}

suspend fun getAllStatisticData(): List<RideDataTuple> {

return withContext(Dispatchers.IO) {

return@withContext ridesDAO.getAllRideData()

}

}

suspend fun removeRideDataById(id: Long) {

withContext(Dispatchers.IO) {

ridesDAO.deleteRideDataById(id)

}

}

}

Разработана функция для считывания данных с полей при нажатии на кнопку (Листинг 8). При успешном добавлении или, если заполнены не все поля выводится соответствующее уведомление.

Листинг 8 – Считывание данных из полей

private fun addRideButtonPressed() {

if (isEditTextsEmpty()) {

viewModel.insertNewRideDataInDatabase(

passengers = binding.passengersEditText.text.toString().toInt(),

start = binding.startEditText.text.toString(),

destination = binding.destinationEditText.text.toString(),

)

Toast.makeText(this, "Данные добавлены в таблицу!", Toast.LENGTH_SHORT)

.show()

} else Toast.makeText(this, "Не все поля заполнены!", Toast.LENGTH_SHORT)

.show()

}

Для отображения данных о поездках из БД в RecyclerView создан адаптер (Листинг 9).

Листинг 9 - Адаптер

class RideAdapter(private val rideItemListener: RideItemListener) :

RecyclerView.Adapter<RideAdapter.RideViewHolder>(), View.OnClickListener {

var data: List<RideDataTuple> = emptyList()

set(newValue) {

val diffUtil = RideDiffUtil(field, newValue)

val diffUtilResult = DiffUtil.calculateDiff(diffUtil)

field = newValue

diffUtilResult.dispatchUpdatesTo(this@RideAdapter)

}

override fun getItemCount(): Int = data.size

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RideViewHolder {

val inflater = LayoutInflater.from(parent.context)

val binding = ItemRideBinding.inflate(inflater, parent, false)

binding.delete.setOnClickListener(this)

return RideViewHolder(binding)

}

override fun onBindViewHolder(holder: RideViewHolder, position: Int) {

val ride = data[position]

with(holder.binding) {

delete.tag = ride

passengersTextView.text = ride.passengers.toString()

startTextView.text = ride.start

destinationTextView.text = ride.destination

}

}

override fun onClick(view: View) {

showPopupMenu(view)

}

private fun showPopupMenu(view: View) {

val popupMenu = PopupMenu(view.context, view)

val ride = view.tag as RideDataTuple

popupMenu.menu.add(0, ID_REMOVE, Menu.NONE, "Удалить поездку")

popupMenu.setOnMenuItemClickListener {

when (it.itemId) {

ID_INFORMATION -> rideItemListener.getInfoAboutRide(ride.id)

ID_REMOVE -> rideItemListener.removeRide(ride.id)

}

return@setOnMenuItemClickListener true

}

popupMenu.show()

}

companion object {

private const val ID_INFORMATION = 1

private const val ID_REMOVE = 2

}

class RideViewHolder(val binding: ItemRideBinding) :

RecyclerView.ViewHolder(binding.root)

}

Вывод: в ходе выполнения практической работы добавлена страница с заказом такси, на которой расположены поля для заполнения, кнопка для добавления заказа в БД и кнопка для перехода к странице с отображение всех поездок из БД через RecyclerView. Создана БД соответственно варианту, определена модель данных, таблица. Разработан DAO интерфейс, реализован адаптер для отображения данных из БД в RecyclerView.

Приложение

Листинг - AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools">

<application

android:allowBackup="true"

android:dataExtractionRules="@xml/data_extraction_rules"

android:fullBackupContent="@xml/backup_rules"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/Theme.MyApplication"

tools:targetApi="31">

<activity

android:name=".Car1Activity"

android:exported="true" />

<activity

android:name=".Car2Activity"

android:exported="true" />

<activity

android:name=".Car3Activity"

android:exported="true" />

<activity

android:name=".Car4Activity"

android:exported="true" />

<activity

android:name=".Car5Activity"

android:exported="true" />

<activity

android:name=".OrderActivity"

android:exported="true" />

<activity

android:name=".NothificationsFragment"

android:exported="false" />

<activity

android:name=".OrderFragment"

android:exported="false" />

<activity

android:name=".ProfileFragment"

android:exported="false" />

<activity

android:name=".CarFragment"

android:exported="false" />

<activity

android:name=".AppActivity"

android:exported="true" />

<activity

android:name=".TaxiActivity"

android:exported="true"

android:label="@string/app_name"/>

<activity

android:name=".AllRidesActivity"

android:exported="true"/>

<activity

android:name=".MainActivity"

android:exported="true">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

</manifest>

Листинг - build.gradle.kts

plugins {

id("com.android.application")

id("org.jetbrains.kotlin.android")

Id("kotlin-kapt")

}

android {

namespace = "com.example.myapplication"

compileSdk = 34

defaultConfig {

applicationId = "com.example.myapplication"

minSdk = 28

targetSdk = 34

versionCode = 1

versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

kapt {

arguments {arg("room.schemaLocation", "$projectDir/schemas")}

}

}

buildTypes {

release {

isMinifyEnabled = false

proguardFiles(

getDefaultProguardFile("proguard-android-optimize.txt"),

"proguard-rules.pro"

)

}

}

compileOptions {

sourceCompatibility = JavaVersion.VERSION_1_8

targetCompatibility = JavaVersion.VERSION_1_8

}

kotlinOptions {

jvmTarget = "1.8"

}

buildFeatures {

viewBinding = true

}

}

dependencies {

Соседние файлы в предмете Разработка мобильных приложений