Я новичок в Kotlin и сейчас пытаюсь создать небольшое приложение для электронных книг для своего проекта. У меня есть база данных комнат для книг, принадлежащих всем пользователям, и ViewModel, которая помогает ее заполнить.
@Entity
data class UsersBook(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
@ColumnInfo val idImage: Int,
@ColumnInfo val title: String,
@ColumnInfo val author: String,
@ColumnInfo val favourited: Boolean,
@ColumnInfo val categories: Category,
@ColumnInfo val nameOwner: String,
@ColumnInfo val rating: Double
)
//Composable for the StoreScreen from NavHost
with(LibraryRoutes.Store) {
composable(route) {
val userBooksVM = koinViewModel()
val addUserBookVm = koinViewModel()
val usersBookState by addUserBookVm.state.collectAsStateWithLifecycle()
val loggedUserVM = koinViewModel()
val stateUser by loggedUserVM.state.collectAsStateWithLifecycle()
StoreScreen(
state,
addUserBookVm.actions,
onSubmit = {
userBooksVM.addUserBook(usersBookState.toUserBook())
},
stateUser,
navController
)
}
}
//This is my StoreScreen
data class Book(
val idImage: Int,
val title: String,
val author: String,
val categories: Category,
val price: Double,
val discount: Int,
val rating: Double
)
@Composable
fun StoreScreen(
state: AddNewUserBookState,
actions: AddNewUserBookActions,
onSubmit: () -> Unit,
usersState: LoggedUserState,
navController: NavHostController
) {
Column(modifier = Modifier.fillMaxSize()) {
val books = remember {
listOf(
Book(
R.drawable.caccia_aperta,
"Caccia Aperta",
"Rob Himmel",
Category.Fantasia,
6.99,
0,
5.0
),
Book(
R.drawable.ridi_che_e_gratis,
"Ridi che è gratis",
"I Carbonchi",
Category.Commedia,
3.50,
0,
4.5
),
Book(
R.drawable.rosa_di_tenebra,
"Rosa Di Tenebra",
"Peony Wentworth",
Category.Romanzo,
11.00,
10,
3.0
)
)
}
LazyRow(
modifier = Modifier.weight(0.5f),
horizontalArrangement = Arrangement.spacedBy(25.dp),
contentPadding = PaddingValues(7.dp, 0.dp, 3.dp, 0.dp)
) {
items(books) {
StoreLibraryItem(
it,
state,
actions,
onSubmit,
usersState,
navController
)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StoreLibraryItem(
item: Book,
state: AddNewUserBookState,
actions: AddNewUserBookActions,
onSubmit: () -> Unit,
usersState: LoggedUserState
) {
Column(
modifier = Modifier.width(167.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = {
actions.setImage(item.idImage)
actions.setTitle(item.title)
actions.setAuthor(item.author)
actions.setToRead(false)
actions.setCategories(item.categories)
actions.setNameOwner(usersState.username)
actions.setRating(item.rating)
onSubmit()
}) {
Text(text = "Buy")
}
}
}
}
По сути, у меня есть StoreScreen с серией книг, каждая из которых имеет кнопку «Купить», которая при нажатии помещает книги в базу данных UserBooks. Однако я не уверен, как с этим справиться, поскольку onClick в коде вызывает onSubmit до того, как все данные будут загружены во вспомогательную ViewModel, в результате чего в базе данных появятся строки с одним или несколькими отсутствующими полями.
Изначально у меня была аналогичная проблема со входом в систему, и кто-то здесь предложил мне использовать оператор When для управления навигацией после проверки имени пользователя и пароля, хотя я мог бы использовать что-то подобное, например TransactionScreen, но я не уверен, сработает ли это, а также это не поможет со вторым вопросом. Я также мог бы использовать предварительно заполненную базу данных для книг, но как мне обработать поле userOwner? поскольку база данных для пользователей находится в памяти, у каждого пользователя есть копия книги в базе данных UserBook, главным образом из-за поля «Избранное». .
Я новичок в Kotlin и сейчас пытаюсь создать небольшое приложение для электронных книг для своего проекта. У меня есть база данных комнат для книг, принадлежащих всем пользователям, и ViewModel, которая помогает ее заполнить. [code]@Entity data class UsersBook( @PrimaryKey(autoGenerate = true) val id: Int = 0, @ColumnInfo val idImage: Int, @ColumnInfo val title: String, @ColumnInfo val author: String, @ColumnInfo val favourited: Boolean, @ColumnInfo val categories: Category, @ColumnInfo val nameOwner: String, @ColumnInfo val rating: Double ) [/code] [code]//Composable for the StoreScreen from NavHost
with(LibraryRoutes.Store) { composable(route) { val userBooksVM = koinViewModel()
val addUserBookVm = koinViewModel() val usersBookState by addUserBookVm.state.collectAsStateWithLifecycle()
val loggedUserVM = koinViewModel() val stateUser by loggedUserVM.state.collectAsStateWithLifecycle() StoreScreen( state, addUserBookVm.actions, onSubmit = { userBooksVM.addUserBook(usersBookState.toUserBook()) }, stateUser, navController ) } } [/code] [code]//Helper ViewModel data class AddNewUserBookState( val idImage: Int = 0, val title: String = "", val author: String = "", val favourited: Boolean = false, val categories: Category = Category.Avventura, val nameOwner: String = "", val rating: Double = 0.0 ) { fun toUserBook() = UsersBook( idImage = idImage, title = title, author = author, favourited= favourited, categories = categories, nameOwner = nameOwner, rating = rating ) } interface AddNewUserBookActions { fun setImage(idImage: Int) fun setTitle(title: String) fun setAuthor(author: String) fun setFavourited(favourited: Boolean) fun setCategories(categories: Category) fun setNameOwner(nameOwner: String) fun setRating(rating: Double) }
class AddUsersBooksViewModel : ViewModel() { private val _state = MutableStateFlow(AddNewUserBookState()) val state = _state.asStateFlow()
val actions = object : AddNewUserBookActions { override fun setImage(idImage: Int) = _state.update { it.copy(idImage = idImage) }
} } [/code] [code]//Database data class UsersBooksState(val usersBooks: List)
class UsersBooksViewModel(private val repository: UsersBooksRepository) : ViewModel() { val state = repository.books.map { UsersBooksState(usersBooks = it) }.stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(), initialValue = UsersBooksState(emptyList()) )
fun addUserBook(usersBook: UsersBook) = viewModelScope.launch { repository.upsert(usersBook) } } [/code] [code]//This is my StoreScreen
data class Book( val idImage: Int, val title: String, val author: String, val categories: Category, val price: Double, val discount: Int, val rating: Double )
@Composable fun StoreScreen( state: AddNewUserBookState, actions: AddNewUserBookActions, onSubmit: () -> Unit, usersState: LoggedUserState, navController: NavHostController ) { Column(modifier = Modifier.fillMaxSize()) { val books = remember { listOf( Book( R.drawable.caccia_aperta, "Caccia Aperta", "Rob Himmel", Category.Fantasia, 6.99, 0, 5.0 ), Book( R.drawable.ridi_che_e_gratis, "Ridi che è gratis", "I Carbonchi", Category.Commedia, 3.50, 0, 4.5 ), Book( R.drawable.rosa_di_tenebra, "Rosa Di Tenebra", "Peony Wentworth", Category.Romanzo, 11.00, 10, 3.0 ) ) }
[/code] По сути, у меня есть StoreScreen с серией книг, каждая из которых имеет кнопку «Купить», которая при нажатии помещает книги в базу данных UserBooks. Однако я не уверен, как с этим справиться, поскольку onClick в коде вызывает onSubmit до того, как все данные будут загружены во вспомогательную ViewModel, в результате чего в базе данных появятся строки с одним или несколькими отсутствующими полями. Изначально у меня была аналогичная проблема со входом в систему, и кто-то здесь предложил мне использовать оператор When для управления навигацией после проверки имени пользователя и пароля, хотя я мог бы использовать что-то подобное, например TransactionScreen, но я не уверен, сработает ли это, а также это не поможет со вторым вопросом. Я также мог бы использовать предварительно заполненную базу данных для книг, но как мне обработать поле userOwner? поскольку база данных для пользователей находится в памяти, у каждого пользователя есть копия книги в базе данных UserBook, главным образом из-за поля «Избранное». .
На моей домашней странице, т. е. «/», перечислены все названия комнат со ссылками, которые должны перенаправлять на эту конкретную комнату с этим именем. Например, нажатие на «Test Room1» должно перенаправить меня в «/room/1» с таким именем. Но он...
На моей домашней странице, т. е. «/», перечислены все названия комнат со ссылками, которые должны перенаправлять на эту конкретную комнату с этим именем. Например, нажатие на «Test Room1» должно перенаправить меня в «/room/1» с таким именем. Но он...
Я добавляю комнату и Sqlite-связанную в приложение Compose Multiplatform, теперь я получаю эту проблему при синхронизации проекта:
:composeApp:wasmJsMain: Could not resolve androidx.room:room-runtime:2.7.0-beta01.
Required by:
project :composeApp...
I want to have a process run continuously starting when one button (button A) is pressed until another button (button B) is pressed in a C# windows forms application, but I am unable to find a good way to do so.