В настоящее время я изучаю Jetpack Compose и пытаюсь реализовать индикатор загрузки во время загрузки данных.
Я управляю состоянием пользовательского интерфейса с помощью управления состоянием (StateFlow/MutableStateFlow). Моя цель — показать загрузчик во время загрузки данных и отобразить содержимое после загрузки данных.
Однако загрузчик не отображается во время загрузки данных.
Как правильно управлять состоянием, чтобы загрузчик отображался во время процесса загрузки, а пользовательский интерфейс правильно обновлялся после того, как данные стали доступны?
Модернизация
private val BASE_URL =
"https://jsonplaceholder.typicode.com/"
object ApiClient {
private val logging : HttpLoggingInterceptor = HttpLoggingInterceptor().setLevel(
HttpLoggingInterceptor.Level.BODY)
private val okHttpClient =
OkHttpClient.Builder()
.addInterceptor(logging)
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.client(okHttpClient)
.build()
val apiService : GetDataService by lazy {
retrofit.create(GetDataService::class.java)
}
}
interface GetDataService {
@GET("users")
suspend fun getData() : List
}
class UserRepository(val api: GetDataService,private val db: AppDatabase) {
suspend fun getUser(): List {
return try {
val apiUsers = api.getData().map { User(firstName = it.name, lastName = it.email) }
db.userDao().insertAlls(apiUsers)
apiUsers
} catch (e: Exception) {
db.userDao().getAll()
}
}
}
data class UserDataModel(val name : String,val username : String, val email : String,val image :String = "")
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAll(): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAlls(users: List)
@Delete
suspend fun delete(users: List)
}
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
// Thread-safe singleton to get the database
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"database-name"
).build()
INSTANCE = instance
instance
}
}
}
}
@Entity
data class User(
@PrimaryKey(autoGenerate = true) val uid: Int = 0,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
@Composable
fun HomeScreen(modifier: Modifier)
{
val context = LocalContext.current
val db = AppDatabase.getDatabase(context)
val repository = UserRepository(ApiClient.apiService,db)
val viewModel: HomeViewModel = viewModel(
factory = HomeViewModelFactory(
application = context.applicationContext as Application,
repository = repository
)
)
val users = viewModel.uiState.collectAsState().value
when(users)
{
is HomeUIState.Loading -> {
CircularProgressIndicator()
}
is HomeUIState.NoData -> {
Text("No data found")
}
is HomeUIState.Error -> {
val errormsg = users.error
Text(errormsg)
}
is HomeUIState.Success ->{
val list = users.list
Column() {
LazyColumn(modifier= Modifier.weight(1f)) {
items(list.size) { index ->
Row() {
AsyncImage("",
contentDescription = list[index].firstName.toString(),
modifier = Modifier.size(100.dp))
list[index].firstName?.let { Text(it) }
}
}
}
Button(onClick = { viewModel.loadMore() }) {
Text("Load More")
}
}
}
}
}
class HomeViewModel(
application: Application,
private val repository: UserRepository
) : AndroidViewModel(application) {
private val _uiState = MutableStateFlow(HomeUIState.Loading)
val uiState: StateFlow = _uiState
private var currentPage = 1
private val pageSize = 3
init {
loadData()
}
fun loadData() {
viewModelScope.launch {
_uiState.value = HomeUIState.Loading
try {
val users = repository.getUser()
if (users.isEmpty()) {
_uiState.value = HomeUIState.NoData
} else {
_uiState.value = HomeUIState.Success(users)
}
} catch (e: Exception) {
_uiState.value = HomeUIState.Error(e.localizedMessage ?: "Something went wrong")
}
}
}
fun loadMore() {
currentPage++
loadData()
}
}
class HomeViewModelFactory(
private val application: Application,
private val repository: UserRepository
) : ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
if (modelClass.isAssignableFrom(HomeViewModel::class.java)) {
return HomeViewModel(application, repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
data class UserDataModel(val name : String,val username : String, val email : String)
sealed interface HomeUIState {
data object Loading : HomeUIState
data object NoData : HomeUIState
data class Success(val list: List) : HomeUIState
data class Error(val error: String) : HomeUIState
}
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
testImplementation("io.mockk:mockk:1.13.8")
implementation("io.coil-kt:coil-compose:2.6.0")
implementation("androidx.room:room-runtime:2.8.4")
implementation("androidx.room:room-ktx:2.8.4")
kapt("androidx.room:room-compiler:2.8.4")
Подробнее здесь: https://stackoverflow.com/questions/799 ... e-state-ma
Индикатор загрузки не отображается при загрузке данных в Jetpack Compose (управление состоянием) ⇐ Android
Форум для тех, кто программирует под Android
1773021476
Anonymous
В настоящее время я изучаю Jetpack Compose и пытаюсь реализовать индикатор загрузки во время загрузки данных.
Я управляю состоянием пользовательского интерфейса с помощью управления состоянием (StateFlow/MutableStateFlow). Моя цель — показать загрузчик во время загрузки данных и отобразить содержимое после загрузки данных.
Однако загрузчик не отображается во время загрузки данных.
Как правильно управлять состоянием, чтобы загрузчик отображался во время процесса загрузки, а пользовательский интерфейс правильно обновлялся после того, как данные стали доступны?
Модернизация
private val BASE_URL =
"https://jsonplaceholder.typicode.com/"
object ApiClient {
private val logging : HttpLoggingInterceptor = HttpLoggingInterceptor().setLevel(
HttpLoggingInterceptor.Level.BODY)
private val okHttpClient =
OkHttpClient.Builder()
.addInterceptor(logging)
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.client(okHttpClient)
.build()
val apiService : GetDataService by lazy {
retrofit.create(GetDataService::class.java)
}
}
interface GetDataService {
@GET("users")
suspend fun getData() : List
}
class UserRepository(val api: GetDataService,private val db: AppDatabase) {
suspend fun getUser(): List {
return try {
val apiUsers = api.getData().map { User(firstName = it.name, lastName = it.email) }
db.userDao().insertAlls(apiUsers)
apiUsers
} catch (e: Exception) {
db.userDao().getAll()
}
}
}
data class UserDataModel(val name : String,val username : String, val email : String,val image :String = "")
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAll(): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAlls(users: List)
@Delete
suspend fun delete(users: List)
}
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
// Thread-safe singleton to get the database
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"database-name"
).build()
INSTANCE = instance
instance
}
}
}
}
@Entity
data class User(
@PrimaryKey(autoGenerate = true) val uid: Int = 0,
@ColumnInfo(name = "first_name") val firstName: String?,
@ColumnInfo(name = "last_name") val lastName: String?
)
@Composable
fun HomeScreen(modifier: Modifier)
{
val context = LocalContext.current
val db = AppDatabase.getDatabase(context)
val repository = UserRepository(ApiClient.apiService,db)
val viewModel: HomeViewModel = viewModel(
factory = HomeViewModelFactory(
application = context.applicationContext as Application,
repository = repository
)
)
val users = viewModel.uiState.collectAsState().value
when(users)
{
is HomeUIState.Loading -> {
CircularProgressIndicator()
}
is HomeUIState.NoData -> {
Text("No data found")
}
is HomeUIState.Error -> {
val errormsg = users.error
Text(errormsg)
}
is HomeUIState.Success ->{
val list = users.list
Column() {
LazyColumn(modifier= Modifier.weight(1f)) {
items(list.size) { index ->
Row() {
AsyncImage("",
contentDescription = list[index].firstName.toString(),
modifier = Modifier.size(100.dp))
list[index].firstName?.let { Text(it) }
}
}
}
Button(onClick = { viewModel.loadMore() }) {
Text("Load More")
}
}
}
}
}
class HomeViewModel(
application: Application,
private val repository: UserRepository
) : AndroidViewModel(application) {
private val _uiState = MutableStateFlow(HomeUIState.Loading)
val uiState: StateFlow = _uiState
private var currentPage = 1
private val pageSize = 3
init {
loadData()
}
fun loadData() {
viewModelScope.launch {
_uiState.value = HomeUIState.Loading
try {
val users = repository.getUser()
if (users.isEmpty()) {
_uiState.value = HomeUIState.NoData
} else {
_uiState.value = HomeUIState.Success(users)
}
} catch (e: Exception) {
_uiState.value = HomeUIState.Error(e.localizedMessage ?: "Something went wrong")
}
}
}
fun loadMore() {
currentPage++
loadData()
}
}
class HomeViewModelFactory(
private val application: Application,
private val repository: UserRepository
) : ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
if (modelClass.isAssignableFrom(HomeViewModel::class.java)) {
return HomeViewModel(application, repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
data class UserDataModel(val name : String,val username : String, val email : String)
sealed interface HomeUIState {
data object Loading : HomeUIState
data object NoData : HomeUIState
data class Success(val list: List) : HomeUIState
data class Error(val error: String) : HomeUIState
}
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
testImplementation("io.mockk:mockk:1.13.8")
implementation("io.coil-kt:coil-compose:2.6.0")
implementation("androidx.room:room-runtime:2.8.4")
implementation("androidx.room:room-ktx:2.8.4")
kapt("androidx.room:room-compiler:2.8.4")
Подробнее здесь: [url]https://stackoverflow.com/questions/79902935/loading-indicator-is-not-showing-while-loading-data-in-jetpack-compose-state-ma[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия