ViewModel #

一、ViewModel概述 #

ViewModel是Jetpack架构组件之一,用于存储和管理UI相关数据。ViewModel在配置更改(如屏幕旋转)时不会销毁,确保数据不会丢失。

1.1 ViewModel的特点 #

  • 生命周期感知
  • 配置更改时数据保留
  • 避免内存泄漏
  • 与UI解耦

1.2 ViewModel生命周期 #

text
Activity创建
    │
    ▼
ViewModel创建
    │
    ▼
Activity运行中(ViewModel保持)
    │
    ├── 屏幕旋转 ──► Activity重建,ViewModel保持
    │
    ▼
Activity销毁
    │
    ▼
ViewModel的onCleared()调用
    │
    ▼
ViewModel销毁

二、基本使用 #

2.1 添加依赖 #

kotlin
dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
}

2.2 创建ViewModel #

kotlin
class MainViewModel : ViewModel() {
    
    private val _count = MutableLiveData<Int>()
    val count: LiveData<Int> = _count
    
    init {
        _count.value = 0
    }
    
    fun increment() {
        _count.value = (_count.value ?: 0) + 1
    }
    
    fun decrement() {
        _count.value = (_count.value ?: 0) - 1
    }
    
    override fun onCleared() {
        super.onCleared()
        // 清理资源
    }
}

2.3 在Activity中使用 #

kotlin
class MainActivity : AppCompatActivity() {
    
    private val viewModel: MainViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        viewModel.count.observe(this) { count ->
            binding.tvCount.text = count.toString()
        }
        
        binding.btnIncrement.setOnClickListener {
            viewModel.increment()
        }
    }
}

2.4 在Fragment中使用 #

kotlin
class MainFragment : Fragment() {
    
    private val viewModel: MainViewModel by viewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        viewModel.count.observe(viewLifecycleOwner) { count ->
            binding.tvCount.text = count.toString()
        }
    }
}

三、AndroidViewModel #

当需要在ViewModel中使用Application Context时,使用AndroidViewModel。

kotlin
class MyViewModel(application: Application) : AndroidViewModel(application) {
    
    private val context = getApplication<Application>()
    
    fun getResourceString(resId: Int): String {
        return context.getString(resId)
    }
}

// 使用
class MainActivity : AppCompatActivity() {
    private val viewModel: MyViewModel by viewModels()
}

四、ViewModel与Repository #

4.1 创建Repository #

kotlin
class UserRepository(
    private val apiService: ApiService,
    private val userDao: UserDao
) {
    fun getUsers(): Flow<List<User>> = flow {
        // 先返回缓存数据
        emit(userDao.getAll())
        
        // 从网络获取数据
        val remoteUsers = apiService.getUsers()
        
        // 保存到数据库
        userDao.insertAll(remoteUsers)
        
        // 返回最新数据
        emit(remoteUsers)
    }
        .catch { e ->
            emit(userDao.getAll())
        }
}

4.2 在ViewModel中使用Repository #

kotlin
class UserViewModel(
    private val repository: UserRepository
) : ViewModel() {
    
    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users
    
    private val _loading = MutableLiveData<Boolean>()
    val loading: LiveData<Boolean> = _loading
    
    private val _error = MutableLiveData<String>()
    val error: LiveData<String> = _error
    
    fun loadUsers() {
        viewModelScope.launch {
            _loading.value = true
            try {
                repository.getUsers()
                    .collect { users ->
                        _users.value = users
                    }
            } catch (e: Exception) {
                _error.value = e.message
            } finally {
                _loading.value = false
            }
        }
    }
}

五、Fragment间共享数据 #

5.1 使用activityViewModels #

kotlin
class MasterFragment : Fragment() {
    
    private val viewModel: SharedViewModel by activityViewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.selectedItem.observe(viewLifecycleOwner) { item ->
            // 更新UI
        }
    }
}

class DetailFragment : Fragment() {
    
    private val viewModel: SharedViewModel by activityViewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.selectedItem.observe(viewLifecycleOwner) { item ->
            // 显示详情
        }
    }
}

class SharedViewModel : ViewModel() {
    private val _selectedItem = MutableLiveData<Item>()
    val selectedItem: LiveData<Item> = _selectedItem
    
    fun selectItem(item: Item) {
        _selectedItem.value = item
    }
}

六、SavedStateHandle #

SavedStateHandle用于保存与恢复数据,即使进程被杀死也能恢复。

kotlin
class DetailViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    
    private val itemId = savedStateHandle.get<String>("itemId")
    
    private val _item = MutableLiveData<Item>()
    val item: LiveData<Item> = _item
    
    init {
        loadItem()
    }
    
    private fun loadItem() {
        viewModelScope.launch {
            // 使用itemId加载数据
        }
    }
}

// 传递参数
class MainActivity : AppCompatActivity() {
    
    private val viewModel: DetailViewModel by viewModels {
        val itemId = intent.getStringExtra("itemId")
        DetailViewModel.Factory(itemId)
    }
}

// 或使用SavedStateViewModelFactory
class DetailViewModel(
    savedStateHandle: SavedStateHandle,
    private val repository: ItemRepository
) : ViewModel() {
    
    companion object {
        const val ITEM_ID_KEY = "itemId"
    }
    
    val itemId: String? = savedStateHandle[ITEM_ID_KEY]
    
    class Factory(
        private val itemId: String,
        private val repository: ItemRepository
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            val savedStateHandle = SavedStateHandle()
            savedStateHandle[ITEM_ID_KEY] = itemId
            return DetailViewModel(savedStateHandle, repository) as T
        }
    }
}

七、ViewModel与依赖注入 #

7.1 使用Hilt #

kotlin
@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: UserRepository
) : ViewModel() {
    
    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users
    
    fun loadUsers() {
        viewModelScope.launch {
            _users.value = repository.getUsers()
        }
    }
}

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    
    private val viewModel: MainViewModel by viewModels()
}

7.2 使用ViewModelFactory #

kotlin
class MainViewModelFactory(
    private val repository: UserRepository
) : ViewModelProvider.Factory {
    
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return MainViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

class MainActivity : AppCompatActivity() {
    
    private val viewModel: MainViewModel by viewModels {
        MainViewModelFactory(UserRepository())
    }
}

八、最佳实践 #

8.1 避免在ViewModel中持有View引用 #

kotlin
// 错误
class MyViewModel(private val view: View) : ViewModel()

// 正确
class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<String>()
    val data: LiveData<String> = _data
}

8.2 使用协程处理异步操作 #

kotlin
class MainViewModel : ViewModel() {
    
    private val _result = MutableLiveData<Result<Data>>()
    val result: LiveData<Result<Data>> = _result
    
    fun fetchData() {
        viewModelScope.launch {
            _result.value = Result.loading()
            try {
                val data = repository.getData()
                _result.value = Result.success(data)
            } catch (e: Exception) {
                _result.value = Result.error(e.message)
            }
        }
    }
}

8.3 使用Flow替代LiveData #

kotlin
class MainViewModel : ViewModel() {
    
    // 使用StateFlow替代LiveData
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()
    
    fun loadData() {
        viewModelScope.launch {
            repository.getData()
                .catch { e ->
                    _uiState.value = UiState.Error(e.message)
                }
                .collect { data ->
                    _uiState.value = UiState.Success(data)
                }
        }
    }
}

// 在Activity中观察
lifecycleScope.launch {
    viewModel.uiState.collect { state ->
        when (state) {
            is UiState.Loading -> showLoading()
            is UiState.Success -> showData(state.data)
            is UiState.Error -> showError(state.message)
        }
    }
}

九、总结 #

本章详细介绍了ViewModel:

  1. ViewModel的基本概念和生命周期
  2. ViewModel的创建和使用
  3. AndroidViewModel的使用
  4. ViewModel与Repository配合
  5. Fragment间共享数据
  6. SavedStateHandle的使用
  7. 依赖注入配置
  8. 最佳实践

ViewModel是Android架构组件的核心,合理使用可以提高代码质量和可维护性。

最后更新:2026-03-26