如何在JetPack Compiss上实现充电屏幕
#kotlin #android #jetpackcompose

通过开发一个Android应用程序,无论是在搜索内部数据库还是通过API,寻找要在屏幕上显示的信息非常常见。

不管我们使用的数据源如何,可以肯定的是,数据可用性将不能总是得到保证!也就是说,虽然数据还没有准备好,但我们可以向我们的通常显示什么?

常见方法之一是呈现屏幕或加载组件。有几种表示加载的方法,它可以是带有“携带”消息的文本,或者是indicadores de progresso do Material Design


tl; dr

对于只希望完整代码测试并达到此结果的您:

App em execução apresentando o indicador de progresso circular. Após 3 segundos, apresenta a lista de produtos com os produtos de amostra

屏幕由此组合表示:

@Composable
fun ProductsListScreen(uiState: ProductsListUiState) {
    val products = uiState.products
    val isLoading = uiState.isLoading
    if (isLoading) {
        Box(modifier = Modifier.fillMaxSize()) {
            CircularProgressIndicator(Modifier.align(Center))
        }
    } else {
        LazyColumn(Modifier.fillMaxSize()) {
            items(products) { p ->
                Column(
                    Modifier
                        .clip(RoundedCornerShape(10.dp))
                        .padding(8.dp)
                        .fillMaxWidth()
                        .border(
                            1.dp,
                            Color.Gray.copy(alpha = 0.5f),
                            RoundedCornerShape(10.dp)
                        )
                        .padding(8.dp)
                ) {
                    Text(text = p.name, fontWeight = FontWeight.Bold, fontSize = 24.sp)
                    Text(text = p.description)
                    Text(
                        text = p.price.toBrazilianCurrency(),
                        fontWeight = FontWeight.Bold,
                        style = TextStyle.Default.copy(color = Color(0xFF4CAF50)),
                        fontSize = 18.sp
                    )
                }
            }
        }
    }
}

产品模型,样本产品清单和how叫:

class ProductsListUiState(
    val products: List<Product> = emptyList(),
    val isLoading: Boolean = true
)

val sampleProducts = List(10) {
    Product(
        name = LoremIpsum(Random.nextInt(1, 5)).values.first(),
        description = LoremIpsum(Random.nextInt(1, 10)).values.first(),
        price = BigDecimal(Random.nextInt(1, 100) * it)
    )
}

class Product(
    val name: String,
    val description: "String,"
    val price: BigDecimal
)

巴西货币构成者:

private fun BigDecimal.toBrazilianCurrency(): String =
    NumberFormat.getCurrencyInstance(
        Locale("pt", "br")
    ).format(this)

带有uistate的状态管理代码:

var uiState by remember {
    mutableStateOf(ProductsListUiState())
}
LaunchedEffect(null) {
    delay(3000)
    uiState = ProductsListUiState(
        products = sampleProducts,
        isLoading = false
    )
}
ProductsListScreen(uiState)

如果您的兴趣是了解这种方式的工作方式以及以这种方式实施它的动机,请继续阅读文章ð


如何表示屏幕上的负载?

在JetPack Compiss中,我们可以提出一个循环进度指标,如下所示:

Box(modifier = Modifier.fillMaxSize()) {
    CircularProgressIndicator(
        Modifier.align(Alignment.Center)
    )
}

App em execução apresentando um indicador de progresso circular indeterminado

请注意,我们有一个不确定的指示器,也就是说,它正在永远旋转!同样,这只是表示的可能性,我们可以使用任何其他组件...非常重要的细节是:

“我们如何写羊毛以在预期的那一刻出现或隐藏负载?” ðρ

国家管理

为此,我们需要在JetPack组成中使用gerenciamento de estado。直接在组合或最建议的ViewModel中,州管理的实施以上。

鉴于本文的目的是专注于仅展示如何制作加载表示形式,我将在组合中进行直接实现。在弄乱方式之前,让我们了解我们需要做的事情:

  • 需要搜索产品的主屏幕
    • 访问屏幕时,它显示了加载表示
    • apons加载产品,显示列表上的产品

现在我们知道了我们需要实施的内容,让我们使用代码。

定义模型并创建产品样本

首先,让我们从产品的模型和一些样本的创建开始:

class Product(
    val name: String,
    val description: String,
    val price: BigDecimal
)

val sampleProducts = List(10) {
    Product(
        name = LoremIpsum(Random.nextInt(1, 5)).values.first(),
        description = LoremIpsum(Random.nextInt(1, 10)).values.first(),
        price = BigDecimal(Random.nextInt(1, 100) * it)
    )
}

以这种方式,我们生成了10种具有随机值,名称,描述和价格的产品。

实施产品列表屏幕

要呈现产品,让我们创建产品列表屏幕:

@Composable
fun ProductsListScreen(products: List<Product>) {
    LazyColumn(Modifier.fillMaxSize()) {
        items(products) { p ->
            Column(
                Modifier
                    .clip(RoundedCornerShape(10.dp))
                    .padding(8.dp)
                    .fillMaxWidth()
                    .border(
                        1.dp,
                        Color.Gray.copy(alpha = 0.5f),
                        RoundedCornerShape(10.dp)
                    )
                    .padding(8.dp)
            ) {
                Text(text = p.name, fontWeight = FontWeight.Bold, fontSize = 24.sp)
                Text(text = p.description)
                Text(
                    text = p.price.toBrazilianCurrency(),
                    fontWeight = FontWeight.Bold,
                    style = TextStyle.Default.copy(color = Color(0xFF4CAF50)),
                    fontSize = 18.sp
                )
            }
        }
    }
}

为了提高价格外观,让我们还添加巴西货币构成者:

private fun BigDecimal.toBrazilianCurrency(): String =
    NumberFormat.getCurrencyInstance(
        Locale("pt", "br")
    ).format(this)

App em execução apresentado uma lista de produtos, com nome, descrição e preço.

通过实施屏幕,我们可以专注于IT的状态管理。

表示通常接口的状态-UI状态

为了表示屏幕数据,我们使用用户或UI State的接口状态模式。 UI状态的想法包含应在屏幕或入口上显示的数据,例如指示数据是否已加载的状态,如果已失败或携带了数据!

可以从任何类别中做出此表示:

class ProductsListUiState(
    val products: List<Product> = emptyList(),
    val isLoading: Boolean = true
)

和入口,我们的屏幕可以通过parano接收ProductsListUiState,并根据UI状态的数据呈现遏制:

@Composable
fun ProductsListScreen(uiState: ProductsListUiState) {
    val products = uiState.products
    val isLoading = uiState.isLoading
    if (isLoading) {
        Box(modifier = Modifier.fillMaxSize()) {
            CircularProgressIndicator(Modifier.align(Center))
        }
    } else {
        LazyColumn(Modifier.fillMaxSize()) { ... }
    }
}

在此配置中,isLoadingtrue,列表没有显示!

测试模拟产品搜索的应用程序

现在我们有表示形式,我们需要修改呼叫的调用,以便搜索信息并更新UI状态:

var uiState by remember {
    mutableStateOf(ProductsListUiState())
}
LaunchedEffect(null) {
    delay(3000)
    uiState = ProductsListUiState(
        products = sampleProducts,
        isLoading = false
    )
}
ProductsListScreen(uiState)

App em execução apresentando o indicador de progresso circular. Após 3 segundos, apresenta a lista de produtos com os produtos de amostra

请参阅现在该应用程序具有循环进度指示器,然后在3秒钟后显示产品列表!你不明白路吗?让我们简要说明

  1. 我们从remember定义了UI状态,因此初始化不受重新分配的影响
  2. LaunchedEffect(null)是一个Side Effect composeble,不会发出视觉组件。
  3. 对不受收入影响的导管的支持的副作用组成部分。通过将null发送为争论,我们表明他只会运行一次!
  4. LaunchedEffect()还允许您执行Coroutines,这就是为什么它不会通过Coroutine应用delay秒锁定相同的执行。
  5. 修改uiState发生时,会发生重新组件,并通过新产品发送了一个新的uiState,并且标志着它不会更多地加载到产品列表屏幕上。li>

了解更多

重要的是要强调,这是一个简单而客观的实施,也就是说,有更复杂和推荐的方法可以使用UI状态实施状态管理。最常用的示例之一是来自ViewModels,尽管它更为复杂,但它将大量的细节解析到App Architecture的注释中。

如果您对这个主题感兴趣,并且想从更结构化的包含中学习,我可以建议您到formação de Jetpack Compose: gerenciamento de estado da Alura。如果您仍然不是订户,我可以为您提供cupom de desconto da assinatura da Alura

您如何看待此实施?我已经知道这些国家管理技术可以在组合中呈现动态遏制吗?喜欢分享其他用于此ð​​

的吨