2024年已经过半了,我作为聋人独立开发者,我经常会时不时反思:自己这半年到底进步了多少?在这篇文章里,我分享一个用 Jetpack Compose、Material3和 Kotlin 语言实现对接接口服务层的开发案例。无论你有没有开发经验,相信这篇文章对你会非常有所帮助。
一、项目背景
Jetpack Compose 是一个非常重要的 UI 工具,摆脱了传统 XML 布局的麻烦,实现了声明式 UI 开发。这篇文章详细介绍如何通过 Jetpack Compose 构建一个简单Demo,实现从远程 API 获取数据、显示分类列表的功能。Demo的主要目标是展示如何通过 ViewModel 和 Retrofit 实现接口服务层的对接。
二、项目开发
我开发一个简单的分类Demo,用户可以看到来自远程 API 的分类信息,主要架构如下:
1. ViewModel 是数据存储和逻辑层,负责和网络服务交互提供数据给 UI 层。
2. 通过 Retrofit 从远程 API 获取分类信息。
2.1 核心组件
• MainActivity:负责应用的入口。
• MainViewModel:处理从 API 获取数据的逻辑。
• RecipeScreen 和 CategoryScreen:负责 UI 的显示。
2.3 代码实现
2.3.1 API 接口和数据模型
通过 Retrofit 构建了 API 接口,定义了数据模型用于接收 JSON 响应:
代码语言:java复制private val retrofit = Retrofit.Builder().baseUrl("https://www.xx.com/api/xx/xx/xx/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val recipeService = retrofit.create(ApiService::class.java)
interface ApiService {
@GET("xx.xx")
suspend fun getCategories(): CategoriesResponse
}
data class Category(
val idCategory: String,
val strCategory: String,
val strCategoryThumb: String,
val strCategoryDescription: String
)
data class CategoriesResponse(val categories: List<Category>)
2.3.1.1 解释Code
Retrofit实例
:使用Retrofit构建器创建一个Retrofit实例,设置基础URL为https://www.xxxx.com/xx/json/xx/,用Gson转换工厂,可以用postman工具调试。
服务接口
:定义了一个名为ApiService的接口,包含名为getCategories的挂起函数,用于异步获取类别信息。
网络请求
:getCategories函数通过GET请求访问categories.php接口,返回类型是CategoriesResponse。
2.3.2 ViewModel 和数据逻辑
在 MainViewModel 中,通过 viewModelScope 执行网络请求,使用 mutableStateOf 管理状态:
代码语言:java复制class MainViewModel : ViewModel() {
private val mCategorieState = mutableStateOf(RecipeState())
val categoriesState: State<RecipeState> = mCategorieState
init {
fetchCategories()
}
private fun fetchCategories() {
viewModelScope.launch {
try {
val response = recipeService.getCategories()
mCategorieState.value = mCategorieState.value.copy(
list = response.categories,
loading = false,
error = null
)
} catch (e: Exception) {
mCategorieState.value = mCategorieState.value.copy(
loading = false,
error = "Error fetching Categories ${e.message}"
)
}
}
}
data class RecipeState(
val loading: Boolean = true,
val list: List<Category> = emptyList(),
val error: String? = null
)
}
2.3.3 编写UI
用Jetpack Compose 显示从 API 获取的分类列表。RecipeScreen 是主界面,根据当前的状态显示加载中、错误或分类数据:
代码语言:java复制@Composable
fun RecipeScreen(modifier: Modifier = Modifier) {
val recipeViewModel: MainViewModel = viewModel()
val viewstate by recipeViewModel.categoriesState
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = "@Nim独立开发者",
color = Color.Black,
style = TextStyle(fontWeight = FontWeight.Bold),
fontSize = 36.sp,
modifier = Modifier.align(Alignment.TopCenter).padding(40.dp)
)
when {
viewstate.loading -> {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
viewstate.error != null -> {
Text(
text = "Error:404",
color = Color.Red,
style = TextStyle(fontWeight = FontWeight.Bold),
fontSize = 36.sp,
modifier = Modifier.align(Alignment.Center)
)
}
else -> {
CategoryScreen(categories = viewstate.list)
}
}
}
}
2.3.4 预览图
代码语言:java复制// 预览,使用假数据
@Preview(showBackground = true)
@Composable
fun PreviewRecipeScreen() {
val fakeCategories = listOf(
Category(
idCategory = "1",
strCategory = "Data1",
strCategoryThumb = "",
strCategoryDescription = "Data1"
),
Category(
idCategory = "2",
strCategory = "Data2",
strCategoryThumb = "",
strCategoryDescription = "Data2"
),
Category(
idCategory = "3",
strCategory = "Data3",
strCategoryThumb = "",
strCategoryDescription = "Data3"
)
)
val viewstate = MainViewModel.RecipeState(
loading = false,
list = fakeCategories,
error = null
)
Box(modifier = Modifier.fillMaxSize()) {
Text(
text = "@Nim独立开发者",
color = Color.Black,
style = TextStyle(fontWeight = FontWeight.Bold),
fontSize = 36.sp,
modifier = Modifier
.align(Alignment.TopCenter)
.padding(40.dp)
)
CategoryScreen(categories = viewstate.list)
}
}
2.3.5 视频演示
三、技术难点
3.1 Jetpack Compose 和传统 View 的思维转换
使用 Jetpack Compose 进行 UI 开发是一种全新的方式,它和传统的 XML 布局完全不同。最大的难点在于掌握声明式 UI 编程的思想,习惯用数据驱动UI的变化。
3.2 网络请求的异常处理
如果从远程 API 获取数据时,可能会遇到各种异常(如网络连接失败等)。在 ViewModel 中,通过 try-catch 捕获异常并和行错误处理,把错误信息传递给 UI。
3.3 UI 状态管理
如何高效管理和更新 UI 状态是一个关键问题。使用 mutableStateOf 管理状态可以保证 UI 在数据变化时自动更新。
四、学习笔记
在开发过程中,总结了以下几点:
4.1 状态管理
Jetpack Compose是单一数据源和不可变状态,这种设计思想和 Compose 的声明式编程方式完美契合。
4.2 ViewModel 结合
通过 ViewModel,可以很方便管理应用的生命周期和网络数据请求。
4.3 假数据和状态模拟
• 假数据:在预览过程中,无法依赖真实的网络请求。所以,手动编写了假数据(如 fakeCategories) @Preview 函数调用,为了在 AS 中进行 UI 预览。
• 使用假状态:通过模拟 MainViewModel.RecipeState,定义了一个没有加载状态和无错误的预览视图,展示成功获取数据的 UI 状态。所以,虽然没有实际的网络请求,开发者同样可以提前查看UI 布局和设计。
五、总结
这次Demo 用 Jetpack Compose 开发App,编写代码实现了从 API 进行数据交互,还编写了如何假设数据UI的正确显示。
有任何问题欢迎提问,感谢大家阅读 )