Android MVVM架构实战:XML与Compose的Hilt+ViewModel整合开发

下面我将详细介绍如何在Android项目中结合使用XML或Compose、Hilt依赖注入和ViewModel来实现MVVM架构模式。

MVVM架构核心组件

  1. Model: 数据层,负责数据获取和存储
  2. View: UI层,XML布局或Compose组件
  3. 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")
        }
    }
}

数据同步策略

  1. 单一数据源:所有数据来自Repository
  2. 状态集中管理:ViewModel是唯一的状态持有者
  3. 数据流向
    • UI事件 → ViewModel → Repository
    • 数据变化 ← Repository ← ViewModel ← UI

最佳实践

  1. ViewModel职责

    • 处理业务逻辑
    • 管理UI状态
    • 协调数据请求
  2. View职责

    • 显示数据
    • 收集用户输入
    • 尽量不包含业务逻辑
  3. Hilt使用建议

    • 使用@Inject构造函数注入简单依赖
    • 使用Module提供复杂依赖
    • Activity/Fragment使用@AndroidEntryPoint
    • Compose使用hiltViewModel()
  4. 状态管理选择

    • XML优先使用LiveData
    • Compose优先使用StateFlow/State
    • 可以同时暴露两种形式供不同UI使用

这种架构结合了MVVM模式的优势,通过Hilt简化了依赖管理,同时兼容传统的XML和现代的Compose两种UI实现方式,非常适合渐进式迁移的项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值