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

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.core:core-ktx:1.9.0")

implementation("androidx.appcompat:appcompat:1.6.1")

implementation("com.google.android.material:material:1.11.0")

implementation("androidx.constraintlayout:constraintlayout:2.1.4")

implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0")

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")

implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")

implementation("androidx.navigation:navigation-ui-ktx:2.7.7")

Implementation ("androidx.Recyclerview:recyclerview:1.2.1")

implementation ("com.github.javafaker:javafaker:1.0.2")

implementation ("com.github.bumptech.glide:glide:4.14.2")

testImplementation("junit:junit:4.13.2")

androidTestImplementation("androidx.test.ext:junit:1.1.5")

androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

}

Листинг - AllRidesActivity.kt

package com.example.myapplication

import android.os.Bundle

import androidx.appcompat.app.AppCompatActivity

import androidx.recyclerview.widget.LinearLayoutManager

import com.example.myapplication.databinding.ActivityAllRidesBinding

class AllRidesActivity : AppCompatActivity() {

private lateinit var binding: ActivityAllRidesBinding

private val viewModel by lazy { AllRidesViewModel(Dependencies.ridesRepository) }

override fun onCreate(savedInstanceState: Bundle?) {

Dependencies.init(applicationContext)

super.onCreate(savedInstanceState)

binding = ActivityAllRidesBinding.inflate(layoutInflater).also { setContentView(it.root) }

viewModel.allStatic.observe(this) { allRides ->

val adapter = RideAdapter(viewModel.rideItemListener)

adapter.data = allRides.reversed()

binding.recyclerView.adapter = adapter

binding.recyclerView.layoutManager = LinearLayoutManager(this)

}

}

}

Листинг - AllRidesViewModel.kt

package com.example.myapplication

import androidx.lifecycle.LiveData

import androidx.lifecycle.MutableLiveData

import androidx.lifecycle.ViewModel

import androidx.lifecycle.viewModelScope

import kotlinx.coroutines.launch

class AllRidesViewModel(private val ridesRepository: RidesRepository) : ViewModel() {

private val _allRides = MutableLiveData<List<RideDataTuple>>()

val allStatic: LiveData<List<RideDataTuple>> = _allRides

init {

getAllRides()

}

val rideItemListener = object : RideItemListener{

override fun getInfoAboutRide(id: Long) {

val rideId = _allRides.value?.indexOfFirst { it.id == id }

if (rideId == -1) return

val rideInfo = _allRides.value?.get(rideId!!)

println(rideInfo)

}

override fun removeRide(id: Long) {

viewModelScope.launch {

ridesRepository.removeRideDataById(id)

getAllRides()

}

}

}

private fun getAllRides() {

viewModelScope.launch {

_allRides.value = ridesRepository.getAllStatisticData()

}

}

}

Листинг – AppDatabase.kt

package com.example.myapplication

import androidx.room.Database

import androidx.room.RoomDatabase

@Database(

version = 1,

entities = [

RidesDbEntity::class

]

)

abstract class AppDatabase : RoomDatabase() {

abstract fun getRidesDao(): RidesDAO

}

Листинг - Dependencies.kt

package com.example.myapplication

import android.content.Context

import androidx.room.Room

object Dependencies {

private lateinit var applicationContext: Context

fun init(context: Context) {

applicationContext = context

}

private val appDatabase: AppDatabase by lazy {

Room.databaseBuilder(applicationContext, AppDatabase::class.java, "database.db")

.createFromAsset("rides.db")

.build()

}

val ridesRepository: RidesRepository by lazy { RidesRepository(appDatabase.getRidesDao()) }

}

Листинг MainActivity.kt:

package com.example.myapplication

import android.content.Intent

import androidx.appcompat.app.AppCompatActivity

import android.os.Bundle

import android.widget.Toast

import com.example.myapplication.databinding.ActivityMainBinding

public class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

private val viewModel by lazy { MainViewModel(Dependencies.ridesRepository) }

override fun onCreate(savedInstanceState: Bundle?) {

Dependencies.init(applicationContext)

super.onCreate(savedInstanceState)

binding = ActivityMainBinding.inflate(layoutInflater).also { setContentView(it.root) }

binding.addRideButton.setOnClickListener { addRideButtonPressed() }

binding.allRidesButton.setOnClickListener { allRidesButtonPressed() }

}

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()

}

private fun allRidesButtonPressed() {

val intent = Intent(this, AllRidesActivity::class.java)

startActivity(intent)

}

private fun isEditTextsEmpty(): Boolean {

val isPassengers = if (binding.passengersEditText.text.toString().isNotBlank()) {

binding.valueTextInputPassengers.error = null

true

} else {

binding.valueTextInputPassengers.error = "Поле не должно быть пустым!"

false

}

val isStart = if (binding.startEditText.text.toString().isNotBlank()) {

binding.valueTextInputStart.error = null

true

} else {

binding.valueTextInputStart.error = "Поле не должно быть пустым!"

false

}

val isDestination = if (binding.destinationEditText.text.toString().isNotBlank()) {

binding.valueTextInputDestination.error = null

true

} else {

binding.valueTextInputDestination.error = "Поле не должно быть пустым!"

false

}

return isPassengers && isStart && isDestination

}

}

Листинг - MainViewModel.kt

package com.example.myapplication

import androidx.lifecycle.ViewModel

import androidx.lifecycle.viewModelScope

import kotlinx.coroutines.launch

class MainViewModel(private val ridesRepository: RidesRepository) : ViewModel() {

fun insertNewRideDataInDatabase(passengers: Int, start: String, destination: String) {

viewModelScope.launch {

val newRide = Ride(passengers, start, destination)

ridesRepository.insertNewRideData(newRide.toRidesDbEntity())

}

}

}

Листинг - Ride.kt

package com.example.myapplication

data class Ride(

val passengers: Int,

val start: String,

val destination: String

) {

fun toRidesDbEntity(): RidesDbEntity = RidesDbEntity(

id = 0,

passengers = passengers,

start = start,

destination = destination,

)

}

Листинг - RideAdapter:

package com.example.myapplication

import android.view.LayoutInflater

import android.view.Menu

import android.view.View

import android.view.ViewGroup

import android.widget.PopupMenu

import androidx.recyclerview.widget.DiffUtil

import androidx.recyclerview.widget.RecyclerView

import com.example.myapplication.databinding.ItemRideBinding

class RideDiffUtil(

private val oldList: List<RideDataTuple>,

private val newList: List<RideDataTuple>

) : DiffUtil.Callback() {

override fun getOldListSize(): Int = oldList.size

override fun getNewListSize(): Int = newList.size

override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {

val oldItem = oldList[oldItemPosition]

val newItem = newList[newItemPosition]

return oldItem.id == newItem.id

}

override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {

val oldItem = oldList[oldItemPosition]

val newItem = newList[newItemPosition]

return oldItem == newItem

}

}

interface RideItemListener {

fun getInfoAboutRide(id: Long)

fun removeRide(id: Long)

}

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)

}

Листинг - RidesDAO.kt

package com.example.myapplication

import androidx.room.Dao

import androidx.room.Insert

import androidx.room.Query

@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)

}

Листинг - RidesDbEntity

package com.example.myapplication

import androidx.room.*

@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

)

Листинг - RidesRepository.kt

package com.example.myapplication

import kotlinx.coroutines.Dispatchers

import kotlinx.coroutines.withContext

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)

}

}

}

Листинг - Tuples.kt

package com.example.myapplication

import androidx.room.ColumnInfo

data class RideDataTuple(

val id: Long,

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

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

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

)

Листинг - activity_all_rides.xml

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

<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/recyclerView"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/light_yellow"/>

Листинг - activity_main.xml

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

<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingTop="50dp"

android:background="@color/light_yellow"

tools:context=".MainActivity">

<TextView

android:id="@+id/title"

style="@style/TextAppearance.AppCompat.Title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/add_new_ride"

android:textStyle="normal|bold"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintHorizontal_bias="0.497"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.textfield.TextInputLayout

android:id="@+id/valueTextInputPassengers"

style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:hint="Количество пассажиров"

android:minWidth="250dp"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/title"

app:layout_constraintVertical_chainStyle="packed">

<com.google.android.material.textfield.TextInputEditText

android:id="@+id/passengersEditText"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:imeOptions="actionDone"

android:inputType="numberDecimal"

android:lines="1" />

</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout

android:id="@+id/valueTextInputStart"

style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:hint="Откуда"

android:minWidth="250dp"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/valueTextInputPassengers"

app:layout_constraintVertical_chainStyle="packed">

<com.google.android.material.textfield.TextInputEditText

android:id="@+id/start_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:imeOptions="actionDone"

android:inputType="text"

android:lines="1"

android:textColorLink="#000000" />

</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout

android:id="@+id/valueTextInputDestination"

style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:hint="Куда"

android:minWidth="250dp"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/valueTextInputStart"

app:layout_constraintVertical_chainStyle="packed">

<com.google.android.material.textfield.TextInputEditText

android:id="@+id/destination_edit_text"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:imeOptions="actionDone"

android:inputType="text"

android:lines="1"

android:textColorLink="#000000" />

</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.button.MaterialButton

android:id="@+id/add_ride_button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:minWidth="250dp"

android:text="@string/add_ride"

android:textAllCaps="true"

android:textColor="@color/light_yellow"

app:backgroundTint="#000000"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/valueTextInputDestination"

app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.None" />

<com.google.android.material.button.MaterialButton

android:id="@+id/all_rides_button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="20dp"

android:minWidth="250dp"

android:text="Все поездки"

android:textAllCaps="true"

android:textColor="@color/light_yellow"

app:backgroundTint="#000000"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintHorizontal_bias="0.496"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@id/add_ride_button"

app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.None" />

<ImageView

android:id="@+id/imageView"

android:layout_width="233dp"

android:layout_height="355dp"

android:layout_marginTop="20dp"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintHorizontal_bias="0.496"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@+id/add_ride_button"

app:srcCompat="@drawable/taxicar" />

</androidx.constraintlayout.widget.ConstraintLayout>

Листинг - item_ride.xml

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

<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"

android:layout_height="wrap_content"

android:padding="15dp"

android:background="@color/light_yellow">

<TextView

android:id="@+id/passengers_text_view"

style="@style/TextAppearance.AppCompat.Body1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:layout_constraintBaseline_toBaselineOf="@id/passengersTitle"

app:layout_constraintStart_toEndOf="@id/passengersTitle"

tools:text=" " />

<TextView

android:id="@+id/passengersTitle"

style="@style/TextAppearance.AppCompat.Body2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:paddingStart="15dp"

android:paddingEnd="5dp"

android:text="@string/passengers"

android:textSize="15sp"

app:layout_constraintTop_toTopOf="parent"

tools:layout_editor_absoluteX="3dp"

tools:ignore="MissingConstraints" />

<TextView

android:id="@+id/destinationTitle"

style="@style/TextAppearance.AppCompat.Body2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:paddingStart="15dp"

android:paddingEnd="5dp"

android:text="@string/destination"

android:textSize="15sp"

app:layout_constraintTop_toBottomOf="@id/startTitle"

tools:layout_editor_absoluteX="3dp"

tools:ignore="MissingConstraints" />

<TextView

android:id="@+id/start_text_view"

style="@style/TextAppearance.AppCompat.Body1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:layout_constraintBaseline_toBaselineOf="@id/startTitle"

app:layout_constraintStart_toEndOf="@id/startTitle"

tools:text=" " />

<TextView

android:id="@+id/destination_text_view"

style="@style/TextAppearance.AppCompat.Body1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:layout_constraintBaseline_toBaselineOf="@id/destinationTitle"

app:layout_constraintStart_toEndOf="@id/destinationTitle"

tools:text=" " />

<TextView

android:id="@+id/startTitle"

style="@style/TextAppearance.AppCompat.Body2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:paddingStart="15dp"

android:paddingEnd="5dp"

android:text="@string/start"

android:textSize="15sp"

app:layout_constraintTop_toBottomOf="@id/passengersTitle"

tools:layout_editor_absoluteX="3dp"

tools:ignore="MissingConstraints" />

<ImageView

android:id="@+id/delete"

android:layout_width="68dp"

android:layout_height="55dp"

android:src="@drawable/baseline_delete_outline_24"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:layout_constraintTop_toTopOf="parent"

app:layout_constraintVertical_bias="0.0" />

</androidx.constraintlayout.widget.ConstraintLayout>

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