xDocxDoc
AI
前端
后端
iOS
Android
Flutter
AI
前端
后端
iOS
Android
Flutter
  • Android数据架构模式

Android数据架构模式

1. 背景与演进历程

Android应用架构经历了从传统MVC到现代响应式模式的演变。早期Activity承担过多职责(视图+控制器),导致代码臃肿、难以测试。2017年Google推出https://developer.android.com/topic/architecture后,MVVM成为官方推荐模式,随后MVI等响应式模式逐渐兴起。

2. 核心架构模式详解

2.1 MVC模式(Model-View-Controller)

// Model层 - 数据模型
data class User(val name: String, val email: String)

// View层 - XML布局(省略)
// Controller层 - Activity/Fragment
class UserActivity : AppCompatActivity() {
    private lateinit var textView: TextView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)
        textView = findViewById(R.id.text_view)
        
        // 控制器直接操作模型和视图
        val user = User("John", "john@example.com")
        updateView(user)
    }
    
    private fun updateView(user: User) {
        textView.text = "${user.name} - ${user.email}"
    }
}

问题:Activity同时承担View和Controller职责,导致代码膨胀(God Activity问题)

2.2 MVP模式(Model-View-Presenter)

// Contract定义接口约束
interface UserContract {
    interface View {
        fun showUser(user: User)
        fun showError(message: String)
    }
    
    interface Presenter {
        fun loadUser()
    }
}

// Presenter实现
class UserPresenter(
    private val view: UserContract.View,
    private val repository: UserRepository
) : UserContract.Presenter {
    
    override fun loadUser() {
        try {
            val user = repository.getUser()
            view.showUser(user)
        } catch (e: Exception) {
            view.showError(e.message ?: "Unknown error")
        }
    }
}

// View实现(Activity)
class UserActivity : AppCompatActivity(), UserContract.View {
    private lateinit var presenter: UserPresenter
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        presenter = UserPresenter(this, UserRepository())
        presenter.loadUser()
    }
    
    override fun showUser(user: User) {
        // 更新UI
    }
    
    override fun showError(message: String) {
        // 显示错误
    }
}

优势:视图与业务逻辑解耦,便于单元测试(Presenter可独立测试)

2.3 MVVM模式(Model-View-ViewModel)

// ViewModel
class UserViewModel : ViewModel() {
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> = _user
    
    private val _error = MutableLiveData<String>()
    val error: LiveData<String> = _error
    
    fun loadUser() {
        viewModelScope.launch {
            try {
                val user = UserRepository().getUser()
                _user.value = user
            } catch (e: Exception) {
                _error.value = e.message
            }
        }
    }
}

// Activity/Fragment(View层)
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // 观察LiveData响应状态变化
        viewModel.user.observe(viewLifecycleOwner) { user ->
            binding.textView.text = "${user.name} - ${user.email}"
        }
        
        viewModel.error.observe(viewLifecycleOwner) { error ->
            Toast.makeText(requireContext(), error, Toast.LENGTH_SHORT).show()
        }
    }
}

核心特性:

  • 数据绑定(Data Binding):减少模板代码
  • 生命周期感知:避免内存泄漏
  • ViewModel保存UI状态:配置变更时数据不丢失

2.4 MVI模式(Model-View-Intent)

// 状态封装
data class UserState(
    val user: User? = null,
    val isLoading: Boolean = false,
    val error: String? = null
)

// Intent(用户意图)
sealed class UserIntent {
    object LoadUser : UserIntent()
    data class UpdateUser(val name: String) : UserIntent()
}

// ViewModel处理状态流转
class UserViewModel : ViewModel() {
    private val _state = MutableStateFlow(UserState())
    val state: StateFlow<UserState> = _state
    
    fun processIntent(intent: UserIntent) {
        when (intent) {
            is UserIntent.LoadUser -> loadUser()
            is UserIntent.UpdateUser -> updateUser(intent.name)
        }
    }
    
    private fun loadUser() {
        _state.update { it.copy(isLoading = true) }
        
        viewModelScope.launch {
            try {
                val user = UserRepository().getUser()
                _state.update { it.copy(user = user, isLoading = false) }
            } catch (e: Exception) {
                _state.update { it.copy(error = e.message, isLoading = false) }
            }
        }
    }
}

单向数据流特性:

  1. 用户操作 → Intent → ViewModel
  2. ViewModel处理 → 更新State
  3. State变化 → 触发UI更新

3. 数据层设计最佳实践

3.1 仓库模式(Repository Pattern)

class UserRepository(
    private val localDataSource: UserLocalDataSource,
    private val remoteDataSource: UserRemoteDataSource
) {
    suspend fun getUser(): User {
        // 优先返回缓存数据
        val localUser = localDataSource.getUser()
        if (localUser != null) {
            return localUser
        }
        
        // 网络请求并缓存
        val remoteUser = remoteDataSource.getUser()
        localDataSource.saveUser(remoteUser)
        return remoteUser
    }
}

3.2 数据源隔离策略

4. 现代架构组件生态体系

4.1 Jetpack组件整合

// 使用Room持久化数据
@Entity
data class User(
    @PrimaryKey val id: Int,
    @ColumnInfo(name = "name") val name: String,
    @ColumnInfo(name = "email") val email: String
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user")
    fun getUsers(): Flow<List<User>>
}

// 使用WorkManager处理后台任务
class UploadWorker(appContext: Context, params: WorkerParameters) :
    Worker(appContext, params) {
    
    override fun doWork(): Result {
        return try {
            // 执行上传操作
            Result.success()
        } catch (e: Exception) {
            Result.failure()
        }
    }
}

4.2 依赖注入(Dagger/Hilt)

@Module
@InstallIn(ViewModelComponent::class)
object AppModule {
    @Provides
    fun provideUserRepository(): UserRepository {
        return UserRepositoryImpl()
    }
}

@HiltViewModel
class UserViewModel @Inject constructor(
    private val repository: UserRepository
) : ViewModel() { /* ... */ }

5. 测试策略

5.1 ViewModel单元测试

@RunWith(JUnit4::class)
class UserViewModelTest {
    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()
    
    private lateinit var viewModel: UserViewModel
    private val mockRepository = mock<UserRepository>()
    
    @Before
    fun setup() {
        viewModel = UserViewModel(mockRepository)
    }
    
    @Test
    fun `loadUser should update state with user data`() = runTest {
        // 准备模拟数据
        val testUser = User("Test", "test@example.com")
        whenever(mockRepository.getUser()).thenReturn(testUser)
        
        // 执行操作
        viewModel.loadUser()
        
        // 验证状态更新
        assertEquals(testUser, viewModel.state.value.user)
    }
}

5.2 UI测试(Espresso)

@RunWith(AndroidJUnit4::class)
class UserActivityTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(UserActivity::class.java)
    
    @Test
    fun shouldDisplayUserData() {
        // 模拟数据
        val testUser = User("Test", "test@example.com")
        
        // 验证UI显示
        onView(withId(R.id.text_name)).check(matches(withText(testUser.name)))
        onView(withId(R.id.text_email)).check(matches(withText(testUser.email)))
    }
}

6. 性能优化考量

6.1 数据流优化

// 使用Flow进行响应式编程
class UserViewModel : ViewModel() {
    val user: Flow<User> = repository.getUserFlow()
        .map { it.toUiModel() }
        .onStart { emit(loadingState) }
        .catch { emit(errorState(it)) }
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = UserState.Loading
        )
}

6.2 内存管理

  • 使用ViewModelScope避免内存泄漏
  • 适时取消协程(viewModelScope.launch自动管理)
  • 使用SavedStateHandle保存关键状态

7. 架构选择指南

MVC

适用场景:简单页面、快速原型

  • ✅ 结构简单
  • ❌ 难以测试、Activity臃肿
MVP

适用场景:需要高测试覆盖率的应用

  • ✅ 视图与逻辑完全解耦
  • ❌ 接口数量多、维护成本高
MVVM

适用场景:大多数业务场景(Google推荐)

  • ✅ 数据绑定减少模板代码
  • ✅ 生命周期感知安全
  • ❌ 双向绑定调试复杂
MVI

适用场景:复杂状态管理、需要可预测数据流

  • ✅ 状态不可变性
  • ✅ 单向数据流易于调试
  • ❌ 样板代码较多

8. 未来趋势

  • 多平台共享:KMM(Kotlin Multiplatform)架构
  • 声明式UI:Jetpack Compose与架构组件深度整合
  • 响应式增强:Flow与Channel的更广泛应用

总结

Android数据架构的核心演进体现了关注点分离和可测试性的持续优化。现代架构选择应基于:

  1. 应用复杂度:简单页面可用MVVM,复杂状态管理推荐MVI
  2. 团队规范:统一架构模式降低维护成本
  3. 测试需求:MVP和MVVM更适合单元测试
  4. 技术债务:逐步重构而非推倒重来

掌握架构模式的核心思想比机械套用更重要,最终目标是构建可维护、可测试、可扩展的Android应用。

最后更新: 2025/8/26 10:07