Исправил вывод в Ангаре и запрос к БД.

This commit is contained in:
ElEgEv 2023-11-27 20:54:27 +04:00
parent 434cb03cac
commit bf6f3fd2e4
11 changed files with 74 additions and 50 deletions

View File

@ -8,10 +8,12 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import ru.ulstu.`is`.pmu.tank.database.AppDataContainer import ru.ulstu.`is`.pmu.tank.database.AppDataContainer
import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.Tank
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
import ru.ulstu.`is`.pmu.tank.repository.TankRepository import ru.ulstu.`is`.pmu.tank.repository.TankRepository
class TankListViewModel( class TankListViewModel(
private val tankRepository: TankRepository private val tankRepository: TankRepository,
private var userId: Long = 100L
) : ViewModel() { ) : ViewModel() {
val tankListUiState: StateFlow<TankListUiState> = tankRepository.getAll().map { val tankListUiState: StateFlow<TankListUiState> = tankRepository.getAll().map {
TankListUiState(it) TankListUiState(it)
@ -21,9 +23,23 @@ class TankListViewModel(
initialValue = TankListUiState() initialValue = TankListUiState()
) )
val usersTanksUiState: StateFlow<UserTankListUiState> = tankRepository.getUserTanks(userId).map {
UserTankListUiState(it)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = AppDataContainer.TIMEOUT),
initialValue = UserTankListUiState()
)
suspend fun deleteTank(tank: Tank) { suspend fun deleteTank(tank: Tank) {
tankRepository.deleteTank(tank) tankRepository.deleteTank(tank)
} }
fun setUserId(uid: Long){
userId = uid
}
} }
data class TankListUiState(val tankList: List<Tank> = listOf()) data class TankListUiState(val tankList: List<Tank> = listOf())
data class UserTankListUiState(val userTankList: List<TankWithNationAndLevel> = listOf())

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.Flow
import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks import ru.ulstu.`is`.pmu.tank.model.LevelWithTanks
import ru.ulstu.`is`.pmu.tank.model.Nation import ru.ulstu.`is`.pmu.tank.model.Nation
import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.Tank
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
@Dao @Dao
interface TankDao { interface TankDao {
@ -20,6 +21,16 @@ interface TankDao {
@Query("select * from tanks where tanks.tankId = :uid") @Query("select * from tanks where tanks.tankId = :uid")
fun getTankUid(uid: Long): Flow<Tank?> fun getTankUid(uid: Long): Flow<Tank?>
//получаем все танки пользователя по его Id
@Query(
"SELECT t.tankId, t.name, t.price, t.image, l.level, n.nationName FROM UserTankCrossRef AS ut " +
"LEFT JOIN tanks as t on ut.tankId = t.tankId " +
"LEFT JOIN levels as l on t.levelId = l.uid " +
"LEFT JOIN nations as n on t.nationId = n.uid " +
"WHERE ut.userId = :uid"
)
fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>>
@Insert @Insert
suspend fun insert(tank: Tank) suspend fun insert(tank: Tank)

View File

@ -3,12 +3,15 @@ package ru.ulstu.`is`.pmu.tank.repository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import ru.ulstu.`is`.pmu.tank.dao.TankDao import ru.ulstu.`is`.pmu.tank.dao.TankDao
import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.Tank
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
class OfflineTankRepository(private val tankDao: TankDao) : TankRepository { class OfflineTankRepository(private val tankDao: TankDao) : TankRepository {
override fun getAll(): Flow<List<Tank>> = tankDao.getAll() override fun getAll(): Flow<List<Tank>> = tankDao.getAll()
override fun getTank(uid: Long): Flow<Tank?> = tankDao.getTankUid(uid) override fun getTank(uid: Long): Flow<Tank?> = tankDao.getTankUid(uid)
override fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>> = tankDao.getUserTanks(uid)
override suspend fun insertTank(tank: Tank) = tankDao.insert(tank) override suspend fun insertTank(tank: Tank) = tankDao.insert(tank)
override suspend fun updateTank(tank: Tank) = tankDao.update(tank) override suspend fun updateTank(tank: Tank) = tankDao.update(tank)

View File

@ -2,10 +2,12 @@ package ru.ulstu.`is`.pmu.tank.repository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.Tank
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
interface TankRepository { interface TankRepository {
fun getAll(): Flow<List<Tank>> fun getAll(): Flow<List<Tank>>
fun getTank(uid: Long): Flow<Tank?> fun getTank(uid: Long): Flow<Tank?>
fun getUserTanks(uid: Long): Flow<List<TankWithNationAndLevel>>
suspend fun insertTank(tank: Tank) suspend fun insertTank(tank: Tank)
suspend fun updateTank(tank: Tank) suspend fun updateTank(tank: Tank)
suspend fun deleteTank(tank: Tank) suspend fun deleteTank(tank: Tank)

View File

@ -20,6 +20,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.key import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
@ -36,6 +37,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
@ -46,64 +48,53 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.ulstu.`is`.pmu.R import ru.ulstu.`is`.pmu.R
import ru.ulstu.`is`.pmu.composeui.navigation.Screen import ru.ulstu.`is`.pmu.composeui.navigation.Screen
import ru.ulstu.`is`.pmu.tank.composeui.list.TankListViewModel
import ru.ulstu.`is`.pmu.tank.database.AppDatabase import ru.ulstu.`is`.pmu.tank.database.AppDatabase
import ru.ulstu.`is`.pmu.tank.model.Level import ru.ulstu.`is`.pmu.tank.model.Level
import ru.ulstu.`is`.pmu.tank.model.Nation import ru.ulstu.`is`.pmu.tank.model.Nation
import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.Tank
import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel
import ru.ulstu.`is`.pmu.tank.model.UserWithTanks import ru.ulstu.`is`.pmu.tank.model.UserWithTanks
import ru.ulstu.`is`.pmu.ui.AppViewModelProvider
import ru.ulstu.`is`.pmu.ui.theme.CustomDark import ru.ulstu.`is`.pmu.ui.theme.CustomDark
import ru.ulstu.`is`.pmu.ui.theme.CustomYellow import ru.ulstu.`is`.pmu.ui.theme.CustomYellow
import ru.ulstu.`is`.pmu.ui.theme.PmudemoTheme import ru.ulstu.`is`.pmu.ui.theme.PmudemoTheme
@Composable
fun Hangar(
navController: NavController?,
viewModel: TankListViewModel = viewModel(factory = AppViewModelProvider.Factory)
){
viewModel.setUserId(100L)
val userTankListUiState by viewModel.usersTanksUiState.collectAsState()
//новый вызов основного списка
Hangar(tankList = userTankListUiState.userTankList )
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun Hangar(navController: NavController) { private fun Hangar(
val navBackStackEntry by navController.currentBackStackEntryAsState() tankList: List<TankWithNationAndLevel>
val currentDestination = navBackStackEntry?.destination ) {
val currentScreen = currentDestination?.route?.let { Screen.getItem(it) }
val context = LocalContext.current
val (users, setUsers) = remember { mutableStateOf<UserWithTanks?>(null) }
val nations = remember { mutableStateListOf<Nation>() }
val levels = remember { mutableStateListOf<Level>() }
fun getData(): Flow<UserWithTanks> {
return flow {
AppDatabase.getInstance(context).userDao().getUserUid(100L).collect() { data ->
emit(data.firstNotNullOf {
UserWithTanks(
user = it.key,
tanks = it.value
)
})
}
}
}
LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
getData().collect() {
setUsers(it)
}
}
}
Column( Column(
verticalArrangement = Arrangement.spacedBy(15.dp) verticalArrangement = Arrangement.spacedBy(15.dp)
) { ) {
val startIndex = 0 val startIndex = 0
if(users != null){ if(tankList.isNotEmpty()){
val countRows = users.tanks.size / 2 val countRows = tankList.size / 2
//проверяем на то, что не всё поместилось в ряды по 2 элемента
val oneLastElem = users.tanks.size % 2
var index = 0 var index = 0
var supportCountRow = countRows var supportCountRow = countRows
for (n in 1..(supportCountRow ?: 1)) { //проверяем на то, что не всё поместилось в ряды по 2 элемента
if(tankList.size % 2 == 1){
supportCountRow++
}
for (n in 1..supportCountRow) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround, horizontalArrangement = Arrangement.SpaceAround,
@ -111,8 +102,14 @@ fun Hangar(navController: NavController) {
.fillMaxWidth() .fillMaxWidth()
.padding(10.dp, 0.dp, 10.dp, 0.dp) .padding(10.dp, 0.dp, 10.dp, 0.dp)
) { ) {
var supportSizeRow = 1
if(n == supportCountRow && supportSizeRow % 2 != 0){
supportSizeRow = 0
}
//цикл для заполнения строки карточек //цикл для заполнения строки карточек
for (m in 0..1) { for (m in 0..supportSizeRow) {
Column( Column(
modifier = Modifier.background(CustomYellow) modifier = Modifier.background(CustomYellow)
) { ) {
@ -132,14 +129,14 @@ fun Hangar(navController: NavController) {
) { ) {
Image( Image(
painter = painterResource( painter = painterResource(
id = users.tanks[index].image id = tankList[index].image
), ),
contentDescription = stringResource(id = R.string.tanks_main_title), contentDescription = stringResource(id = R.string.tanks_main_title),
modifier = Modifier modifier = Modifier
.height(130.dp) .height(130.dp)
) )
Text( Text(
text = users.tanks[index].name, text = tankList[index].name,
fontSize = 20.sp, fontSize = 20.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = Color.Black, color = Color.Black,
@ -147,7 +144,7 @@ fun Hangar(navController: NavController) {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Text( Text(
text = "Нация: " + users.tanks[index].nationName, text = "Нация: " + tankList[index].nationName,
fontSize = 17.sp, fontSize = 17.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = Color.Black, color = Color.Black,
@ -155,7 +152,7 @@ fun Hangar(navController: NavController) {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Text( Text(
text = "Уровень: " + users.tanks[index].level.toString(), text = "Уровень: " + tankList[index].level.toString(),
fontSize = 17.sp, fontSize = 17.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = Color.Black, color = Color.Black,
@ -163,7 +160,7 @@ fun Hangar(navController: NavController) {
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Text( Text(
text = "Стоимость: " + users.tanks[index].price.toString(), text = "Стоимость: " + tankList[index].price.toString(),
fontSize = 17.sp, fontSize = 17.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = Color.Black, color = Color.Black,
@ -175,11 +172,6 @@ fun Hangar(navController: NavController) {
} }
index++ index++
//если надо будет допечатать ещё один элемент
if (n == supportCountRow && oneLastElem != 0) {
supportCountRow = oneLastElem
}
} }
} }
Spacer(Modifier.height(20.dp)) Spacer(Modifier.height(20.dp))