Android MVVM架构实战:XML与Compose的Hilt+ViewModel整合开发
下面我将详细介绍如何在Android项目中结合使用XML或Compose、Hilt依赖注入和ViewModel来实现MVVM架构模式。
MVVM架构核心组件
- Model: 数据层,负责数据获取和存储
- View: UI层,XML布局或Compose组件
- ViewModel: 业务逻辑层,连接View和Model
项目配置
1. 添加依赖项 (build.gradle)
// Hilt
implementation "com.google.dagger:hilt-android:2.48"
kapt "com.google.dagger:hilt-android-compiler:2.48"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
// 如果是Compose
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2"
// LiveData (XML中使用)
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2"
// Compose (可选)
implementation "androidx.compose.runtime:runtime-livedata:1.5.4"
使用Hilt进行依赖注入
1. 设置Hilt Application
@HiltAndroidApp
class MyApplication : Application()
2. 创建Module提供依赖
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideRepository(): MyRepository {
return MyRepositoryImpl()
}
}
实现MVVM架构
1. Model层 (Repository)
interface MyRepository {
suspend fun fetchData(): String
fun getLiveData(): LiveData<String>
}
class MyRepositoryImpl @Inject constructor() : MyRepository {
private val _data = MutableLiveData<String>("Initial Data")
override suspend fun fetchData(): String {
// 模拟网络请求
delay(1000)
_data.postValue("Fetched Data")
return "Fetched Data"
}
override fun getLiveData(): LiveData<String> = _data
}
2. ViewModel层
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: MyRepository
) : ViewModel() {
private val _uiState = MutableStateFlow("")
val uiState = _uiState.asStateFlow()
val liveData = repository.getLiveData()
fun fetchData() {
viewModelScope.launch {
_uiState.value = "Loading..."
val result = repository.fetchData()
_uiState.value = result
}
}
}
XML实现方式
1. XML布局 (res/layout/activity_xml.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fetch Data"/>
</LinearLayout>
2. Activity实现
@AndroidEntryPoint
class XmlActivity : AppCompatActivity() {
private lateinit var binding: ActivityXmlBinding
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityXmlBinding.inflate(layoutInflater)
setContentView(binding.root)
// 观察LiveData (XML方式)
viewModel.liveData.observe(this) { data ->
binding.textView.text = data
}
// 观察StateFlow (也可以使用)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
binding.textView.text = state
}
}
}
binding.button.setOnClickListener {
viewModel.fetchData()
}
}
}
Compose实现方式
1. Compose Activity
@AndroidEntryPoint
class ComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
ComposeScreen()
}
}
}
}
@Composable
fun ComposeScreen(viewModel: MyViewModel = hiltViewModel()) {
val uiState by viewModel.uiState.collectAsState()
val liveDataValue by viewModel.liveData.observeAsState("")
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "StateFlow: $uiState")
Text(text = "LiveData: $liveDataValue")
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { viewModel.fetchData() }) {
Text("Fetch Data")
}
}
}
数据同步策略
- 单一数据源:所有数据来自Repository
- 状态集中管理:ViewModel是唯一的状态持有者
- 数据流向:
- UI事件 → ViewModel → Repository
- 数据变化 ← Repository ← ViewModel ← UI
最佳实践
-
ViewModel职责:
- 处理业务逻辑
- 管理UI状态
- 协调数据请求
-
View职责:
- 显示数据
- 收集用户输入
- 尽量不包含业务逻辑
-
Hilt使用建议:
- 使用
@Inject
构造函数注入简单依赖 - 使用Module提供复杂依赖
- Activity/Fragment使用
@AndroidEntryPoint
- Compose使用
hiltViewModel()
- 使用
-
状态管理选择:
- XML优先使用LiveData
- Compose优先使用StateFlow/State
- 可以同时暴露两种形式供不同UI使用
这种架构结合了MVVM模式的优势,通过Hilt简化了依赖管理,同时兼容传统的XML和现代的Compose两种UI实现方式,非常适合渐进式迁移的项目。