不练不熟,不写就忘 之 compose 之 一些需要知道的东西
SharedPreferences:逐步淘汰,仅用于兼容老项目;DataStore:Google 官方推荐,适配 Jetpack/Compose,适合中低性能需求的结构化存储;MMKV:性能王者,功能全面,是大多数场景的最优解(尤其是高频读写、大数据场景)。
1 compose 推荐你 使用 【单Activity】
整个应用只有一个 Activity(通常是 MainActivity),作为容器承载所有 UI 内容;页面切换通过 ** 导航组件(Navigation Compose)** 管理不同的 @Composable 函数(页面),本质是同一 Activity 内的 Composable 重组与替换。
实现方式
依赖 Navigation Compose 库,通过导航图(NavGraph)定义页面路由,用 NavHost 承载页面切换:
// 1. 定义路由
sealed class Screen(val route: String) {
object Home : Screen("home")
object Detail : Screen("detail/{id}") {
fun createRoute(id: Int) = "detail/$id"
}
}
// 2. 导航宿主(Activity 中)
@Composable
fun AppNavHost(navController: NavController) {
NavHost(
navController = navController,
startDestination = Screen.Home.route
) {
composable(Screen.Home.route) {
HomeScreen(navController) // 首页 Composable
}
composable(
route = Screen.Detail.route,
arguments = listOf(navArgument("id") { type = NavType.IntType })
) { backStackEntry ->
val id = backStackEntry.arguments?.getInt("id") ?: 0
DetailScreen(id = id) // 详情页 Composable
}
}
}
// 3. Activity 入口
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
AppTheme {
AppNavHost(navController = navController)
}
}
}
}
优势
- 性能更优:Activity 启动开销远大于 Composable 重组,页面切换更流畅;
- 状态共享便捷:同一 Activity 内可通过 ViewModel、remember 或全局状态(如 StateFlow)轻松共享数据;
- 导航控制灵活:支持嵌套导航、深层链接、动画过渡等,且可通过 NavController 统一管理返回栈;
- 符合 Compose 设计理念:以 Composable 为核心,避免多 Activity 间的上下文传递和生命周期管理复杂度。
局限性
- 若需完全隔离的组件(如独立进程、系统级隔离),单 Activity 无法满足;
- 极端复杂的应用(如模块化强隔离)可能需结合多 Activity,但仍推荐单 Activity 为主。
2 compose 一般要搭配 ViewModel使用
ViewModel 的核心作用是管理 UI 相关状态、数据持久化(屏幕旋转 / 配置变更)、解耦 UI 与业务逻辑,与 Compose 天然契合。
结合方式
通过 viewModel() 函数在 Composable 中获取 ViewModel 实例(自动关联 Lifecycle,生命周期与宿主 Activity/Fragment 一致):
// 定义 ViewModel
class HomeViewModel : ViewModel() {
private val _uiState = MutableStateFlow(HomeUiState())
val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()
fun fetchData() {
// 模拟数据请求
viewModelScope.launch {
_uiState.value = _uiState.value.copy(isLoading = true)
// ... 业务逻辑
_uiState.value = _uiState.value.copy(data = "加载完成", isLoading = false)
}
}
}
// Compose 中使用
@Composable
fun HomeScreen(
viewModel: HomeViewModel = viewModel() // 自动创建/获取 ViewModel
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
if (uiState.isLoading) {
LoadingIndicator()
} else {
Text(text = uiState.data)
}
}
优势
- 状态持久化:ViewModel 独立于 Composable 重组和配置变更(如屏幕旋转),数据不丢失;
- 生命周期安全:viewModelScope 自动跟随 ViewModel 生命周期取消协程,避免内存泄漏;
- 状态驱动 UI:ViewModel 暴露可观察状态(StateFlow/LiveData),Compose 通过 collectAsStateWithLifecycle() 自动响应状态变化。
3 compose中 使用Application
Compose 开发中仍然需要使用 Application 类,但它的角色和传统 Android 开发略有不同 ——Application 作为应用的全局上下文和生命周期入口,负责初始化全局资源、依赖注入、全局状态管理等核心工作,与 Compose 本身的 UI 渲染机制并不冲突,反而能为 Compose 提供必要的全局支持。
全局上下文与资源访问
- 访问全局资源(如字符串、主题、SharedPreferences);
- 初始化第三方库(如网络、数据库、图片加载框架);
- 在 Compose 中通过 LocalContext 获取应用上下文(底层关联 Application)
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 初始化全局库(如 Retrofit、Room)
RetrofitClient.init(this)
// 初始化全局状态容器(如 DataStore)
DataStoreManager.init(this)
}
}
// Compose 中获取应用上下文
@Composable
fun ExampleComposable() {
val context = LocalContext.current
val appContext = context.applicationContext as MyApp
// 使用全局资源或服务
}
全局状态管理
Application 可承载跨组件的全局状态(如用户登录状态、应用配置),通过单例或观察者模式供 Compose 访问:
class MyApp : Application() {
// 全局状态(示例:用户登录状态)
val userState = MutableStateFlow<User?>(null)
companion object {
// 全局获取 Application 实例
lateinit var instance: MyApp
private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
// Compose 中观察全局状态
@Composable
fun GlobalStateObserver() {
val user by MyApp.instance.userState.collectAsStateWithLifecycle()
if (user != null) {
Text("已登录:${user?.name}")
}
}
应用生命周期监听
Application 可监听应用的全局生命周期事件(如前台 / 后台切换),通过回调通知 Compose 调整 UI 或逻辑
class MyApp : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppForeground() {
// 应用进入前台,通知 Compose 刷新数据
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppBackground() {
// 应用进入后台,暂停任务
}
}
4 compose 的数据缓存


总结:
- SharedPreferences:逐步淘汰,仅用于兼容老项目;
- DataStore:Google 官方推荐,适配 Jetpack/Compose,适合中低性能需求的结构化存储;
- MMKV:性能王者,功能全面,是大多数场景的最优解(尤其是高频读写、大数据场景)。
5 compose 集成一些第三方的view,使用AndroidView ,例如 高德地图
在 Compose 中使用高德地图需要通过 AndroidView 来集成原生的 MapView,以下是完整的实现方案:
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.amap.api.maps.AMap
import com.amap.api.maps.MapView
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.MarkerOptions
@Composable
fun AmapView(
modifier: Modifier = Modifier,
initialLatLng: LatLng = LatLng(39.906901, 116.397972), // 默认北京坐标
onMapReady: (AMap) -> Unit = {}
) {
val context = LocalContext.current
var mapView by remember { mutableStateOf<MapView?>(null) }
var aMap by remember { mutableStateOf<AMap?>(null) }
// 使用AndroidView集成原生MapView
AndroidView(
modifier = modifier.fillMaxSize(),
factory = { ctx ->
// 创建MapView容器
val container = FrameLayout(ctx)
val mapViewInstance = MapView(ctx)
// 设置MapView布局参数
mapViewInstance.layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
container.addView(mapViewInstance)
// 初始化地图
mapViewInstance.onCreate(Bundle())
mapViewInstance.getMapAsync { aMapInstance ->
aMap = aMapInstance
// 初始化地图配置
setupMap(aMapInstance, initialLatLng)
onMapReady(aMapInstance)
}
mapView = mapViewInstance
container
},
update = { container ->
// 地图更新逻辑(如果需要)
}
)
// 处理MapView生命周期
DisposableEffect(Unit) {
onDispose {
mapView?.onDestroy()
aMap = null
}
}
}
// 地图初始化配置
private fun setupMap(aMap: AMap, initialLatLng: LatLng) {
// 设置地图缩放级别
aMap.moveCamera(com.amap.api.maps.CameraUpdateFactory.newLatLngZoom(initialLatLng, 15f))
// 显示交通图层
aMap.isTrafficEnabled = true
// 显示缩放控件
aMap.uiSettings.isZoomControlsEnabled = true
// 添加标记
aMap.addMarker(
MarkerOptions()
.position(initialLatLng)
.title("默认位置")
.snippet("这是默认标记点")
)
// 设置地图类型(普通地图/卫星地图)
aMap.mapType = AMap.MAP_TYPE_NORMAL
}
// 带生命周期管理的地图组件(Activity/Fragment级别)
@Composable
fun AmapWithLifecycle(
modifier: Modifier = Modifier,
onMapReady: (AMap) -> Unit = {}
) {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
// 监听生命周期事件
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
mapView?.let { mv ->
when (event) {
Lifecycle.Event.ON_RESUME -> mv.onResume()
Lifecycle.Event.ON_PAUSE -> mv.onPause()
Lifecycle.Event.ON_DESTROY -> mv.onDestroy()
Lifecycle.Event.ON_START -> mv.onStart()
Lifecycle.Event.ON_STOP -> mv.onStop()
else -> {}
}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
AmapView(
modifier = modifier,
onMapReady = onMapReady
)
}
// 使用示例
@Composable
fun MapScreen() {
Column(modifier = Modifier.fillMaxSize()) {
// 顶部标题栏
Text(
text = "高德地图示例",
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.headlineSmall
)
// 高德地图组件
AmapWithLifecycle(
modifier = Modifier.weight(1f),
onMapReady = { aMap ->
// 地图加载完成后的自定义操作
aMap.setOnMapClickListener { latLng ->
// 点击地图添加标记
aMap.addMarker(
MarkerOptions()
.position(latLng)
.title("点击位置")
.snippet("纬度: ${latLng.latitude}, 经度: ${latLng.longitude}")
)
}
}
)
}
}
更多推荐
所有评论(0)