- Счетчик приращения...
- вызывается с id=0
Код: Выделить всё
incrementCount() - Счетчик загружен из БД: 0
Код: Выделить всё
@Entity
data class CounterEntity(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val count: Int)
Код: Выделить всё
@Dao
interface CounterDataAccessObject {
@Query("SELECT count FROM CounterEntity WHERE id = :id")
suspend fun getCount(id: Int): Int?
@Query("UPDATE CounterEntity SET count = count + 1 WHERE id = :id")
suspend fun incrementCount(id: Int) {
Log.d("CounterDAO", "incrementCount() called with id=$id")
}
@Query("UPDATE CounterEntity SET count = count - 1 WHERE id = :id")
suspend fun decrementCount(id: Int)
}
Код: Выделить всё
@Database(
entities = [CounterEntity::class],
version = 1,
exportSchema = false
)
abstract class CounterDatabase : RoomDatabase() {
abstract fun counterDataAccessObject() : CounterDataAccessObject
companion object {
@Volatile
private var INSTANCE: CounterDatabase? = null
fun getDatabase(context: Context): CounterDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
CounterDatabase::class.java,
"CounterDatabase"
).build()
INSTANCE = instance
instance
}
}
}
}
Код: Выделить всё
package com.example.counter.app.III_data
import com.example.counter.app.IV_database.CounterDataAccessObject
import javax.inject.Inject
class CounterLocalDataSource @Inject constructor(
private val counterDatabaseAccessObject: CounterDataAccessObject
) {
// liest aktuellen count
suspend fun getCount(): Int {
//ensureCounterExists()
return counterDatabaseAccessObject.getCount(1) ?: 0
}
// erhöht den aktuelle count um 1
suspend fun incrementCount() {
//ensureCounterExists()
counterDatabaseAccessObject.incrementCount(1)
}
suspend fun decrementCount() {
//ensureCounterExists()
counterDatabaseAccessObject.decrementCount(1)
}
suspend fun resetCount() {
counterDatabaseAccessObject.resetCount(1)
}
}
Код: Выделить всё
package com.example.counter.app.III_data
import javax.inject.Inject
class CounterRepository @Inject constructor(
private val counterLocalDataSource: CounterLocalDataSource
) {
suspend fun getCount(): Int {
return counterLocalDataSource.getCount()
}
suspend fun incrementCount() {
counterLocalDataSource.incrementCount()
}
suspend fun decrementCount() {
counterLocalDataSource.decrementCount()
}
suspend fun resetCount() {
counterLocalDataSource.resetCount()
}
}
Код: Выделить всё
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideCounterDatabase(@ApplicationContext context: Context): CounterDatabase {
return CounterDatabase.getDatabase(context)
}
@Provides
@Singleton
fun provideCounterDataAccessObject(counterDatabase: CounterDatabase): CounterDataAccessObject {
return counterDatabase.counterDataAccessObject()
}
@Provides
@Singleton
fun provideCounterLocalDataSource(counterDataAccessObject: CounterDataAccessObject): CounterLocalDataSource {
return CounterLocalDataSource(counterDataAccessObject)
}
@Provides
@Singleton
fun provideCounterRepository(counterLocalDataSource: CounterLocalDataSource): CounterRepository {
return CounterRepository(counterLocalDataSource)
}
}
Код: Выделить всё
@HiltViewModel
class CounterViewModel @Inject constructor(
private val counterRepository: CounterRepository
) : ViewModel() {
// interner veränderbarer Zustand
private val _uiState: MutableStateFlow = MutableStateFlow(CounterUiState())
// öffentlicher unveränderlicher Zugriff
val uiState: StateFlow = _uiState.asStateFlow()
// initialen Zählstand aus dem Repository laden
init {
loadCount()
}
// Zählstand aus dem Repository laden
fun loadCount() {
viewModelScope.launch{
val count: Int = counterRepository.getCount()
Log.d("CounterViewModel", "Loaded count from DB: $count")
_uiState.update { it.copy(count = count) }
}
}
fun increment() {
viewModelScope.launch {
Log.d("CounterViewModel", "Incrementing counter...")
counterRepository.incrementCount()
loadCount()
}
}
fun decrement() {
viewModelScope.launch {
counterRepository.decrementCount()
loadCount()
}
}
}
Код: Выделить всё
data class CounterUiState(
val count: Int = 0
)
Код: Выделить всё
@Composable
fun CounterScreen(
modifier: Modifier = Modifier,
count: Int,
onIncrement: () -> Unit,
onDecrement: () -> Unit,
) {
Column(
modifier = modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Counter: $count",
color = MaterialTheme.colorScheme.onBackground,
fontSize = 20.sp,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(10.dp))
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Button(
modifier = Modifier.width(80.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary, //
contentColor = MaterialTheme.colorScheme.onPrimary), //
onClick = onDecrement ) {
Text("-")
}
Spacer(modifier = Modifier.width(10.dp))
Button(
modifier = Modifier.width(80.dp),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary, //
contentColor = MaterialTheme.colorScheme.onPrimary), //
onClick = onIncrement ) {
Text("+")
}
}
}
}
Код: Выделить всё
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
CounterTheme(
darkTheme = false
) {
val counterViewModel: CounterViewModel by viewModels()
val state by counterViewModel.uiState.collectAsStateWithLifecycle()
LaunchedEffect(state) {
Log.d("MainActivity", "UI State updated: $state")
}
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
CounterScreen(
modifier = Modifier.padding(innerPadding),
count = state.count,
onIncrement = counterViewModel::increment,
onDecrement = counterViewModel::decrement,
)
}
}
}
}
}
Код: Выделить всё
@HiltAndroidApp
class MyApp : Application() {}