Android开发中的前五个代码异味:Jetpack Compose UI和MVVM

这篇具有很好参考价值的文章主要介绍了Android开发中的前五个代码异味:Jetpack Compose UI和MVVM。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Android开发中的前五个代码异味:Jetpack Compose UI和MVVM

Android开发中的前五个代码异味:Jetpack Compose UI和MVVM

代码异味是指软件代码中潜在问题的指标,可能并不一定是错误,但可能会导致问题,如增加维护复杂性、降低性能或降低可读性。我们将探讨Android开发中的前五个代码异味,其中包括使用Jetpack Compose UI和Model-View-ViewModel(MVVM)架构的示例。

1. 上帝对象或上帝类:

上帝对象或上帝类是指试图做太多事情的单个类,违反了单一职责原则。在Android开发中,这可能会使代码更难理解、维护和修改。

示例:

我们将以一个充当“上帝对象”的ViewModel为例,然后使用存储库模式进行重构。

上帝对象ViewModel示例:

class GodObjectViewModel : ViewModel() {
    private val apiService = ApiService()
    private val database = AppDatabase.getInstance()

    // LiveData to expose data to the UI
    private val _data = MutableLiveData<List<DataItem>>()
    val data: LiveData<List<DataItem>> = _data

    init {
        loadData()
    }

    private fun loadData() {
        viewModelScope.launch {
            // Fetch data from API
            val apiData = apiService.getData()

            // Save data to database
            database.dataDao().insertAll(apiData)

            // Load data from database
            val dbData = database.dataDao().getAll()

            // Transform data
            val transformedData = transformData(dbData)

            // Update LiveData
            _data.value = transformedData
        }
    }

    private fun transformData(input: List<DataItem>): List<DataItem> {
        // Perform some transformations on the data
        // ...
        return transformedData
    }
}

使用仓库模式重构后的 ViewModel:

class RefactoredViewModel(private val dataRepository: DataRepository) : ViewModel() {
    // LiveData to expose data to the UI
    private val _data = MutableLiveData<List<DataItem>>()
    val data: LiveData<List<DataItem>> = _data

    init {
        loadData()
    }

    private fun loadData() {
        viewModelScope.launch {
            // Fetch data using the repository
            val transformedData = dataRepository.fetchData()

            // Update LiveData
            _data.value = transformedData
        }
    }
}

为了改进代码,我们使用仓库模式对 ViewModel 进行了重构。我们创建了一个独立的 DataRepository 类,它负责处理 API 调用、数据库操作和数据转换的职责。然后,重构后的 ViewModel 被简化为仅专注于通过委托数据获取任务到 DataRepository 来向 UI 公开数据。

2. 深层继承层次结构:

过度使用继承可能导致代码复杂且难以维护。在适当的情况下,应优先考虑组合而非继承。

示例:

使用 Kotlin 和 Jetpack Compose,展示了一个深层的继承层次结构,然后使用组合对其进行了重构。

abstract class BaseComposable {
    abstract fun DrawScope.draw()
}

class FirstLevelComposable : BaseComposable() {
    override fun DrawScope.draw() {
        // Implement some functionality
    }
}

class SecondLevelComposable : FirstLevelComposable() {
    override fun DrawScope.draw() {
        super.draw()
        // Add more functionality
    }
}

class ThirdLevelComposable : SecondLevelComposable() {
    override fun DrawScope.draw() {
        super.draw()
        // Add even more functionality
    }
}

@Composable
fun DeepInheritanceHierarchyExample() {
    val thirdLevelComposable = ThirdLevelComposable()

    Canvas(modifier = Modifier.fillMaxSize()) {
        thirdLevelComposable.draw()
    }
}

使用组合进行重构:

@Composable
fun BaseComposable() {
    // Implement some functionality
}

@Composable
fun FirstLevelComposable() {
    BaseComposable()
    // Add more functionality
}

@Composable
fun SecondLevelComposable() {
    FirstLevelComposable()
    // Add even more functionality
}

@Composable
fun CompositionExample() {
    Canvas(modifier = Modifier.fillMaxSize()) {
        SecondLevelComposable()
    }
}

在重构的示例中,我们使用组合替换了深度继承层次结构,使代码更易于理解和维护。我们创建了小型可重用的 Composable 函数,而不是从多个父类继承,可以组合这些函数来实现所需的功能。这种方法更加灵活,并遵循 Jetpack Compose 的原则。

3. 硬编码值或“魔法数字”:

硬编码值可能会使代码不够灵活,难以维护。使用常量或资源文件存储可能会发生更改的值。
示例:
在 Jetpack Compose 中,我们不使用像 colors.xml、dimens.xml 和 strings.xml 这样的 XML 文件。相反,我们在 Kotlin 文件中定义这些资源。以下是一个使用硬编码值的示例,并对其进行重构以使用常量:

硬编码代码示例:

import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@Composable
fun HardcodedValuesExample() {
    Text(
        text = "Hello, World!",
        color = Color(0xFF3F51B5),
        modifier = Modifier.padding(16.dp)
    )
}

使用常量进行重构:
创建一个专门的文件,例如Theme.kt

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

object Constants {
    val primaryColor = Color(0xFF3F51B5)
    val defaultPadding = 16.dp
}

更新 HardcodedValuesExample 使用常量:

import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import Constants.primaryColor
import Constants.defaultPadding

@Composable
fun RefactoredValuesExample() {
    Text(
        text = "Hello, World!",
        color = primaryColor,
        modifier = Modifier.padding(defaultPadding)
    )
}

在重构的示例中,我们使用在专门的文件中定义的常量来代替硬编码的值。这使得代码更易于维护和更新。对于文本字符串,您可以使用类似的方法,在单独的文件中定义字符串常量,并在您的 Composables 中使用它们。

4. 长方法或类:

长方法或类难以理解和维护。将它们拆分成更小、更集中的功能单元。
示例:
使用 Kotlin 和 Jetpack Compose,我们有一个 ViewModel 类,其中包含一个长方法,处理数据转换和业务逻辑。我们将通过将方法拆分为更小、更专注的函数来进行重构。
长方法示例:

class LongMethodViewModel : ViewModel() {
    // ...

    private fun processData(data: List<DataItem>): List<ProcessedDataItem> {
        // Step 1: Filter the data
        val filteredData = data.filter { item ->
            item.isActive && item.value > 10
        }

        // Step 2: Transform the data
        val transformedData = filteredData.map { item ->
            ProcessedDataItem(
                id = item.id,
                displayName = "${item.name} (${item.value})",
                important = item.value > 50
            )
        }

        // Step 3: Sort the data
        val sortedData = transformedData.sortedByDescending { item ->
            item.important
        }

        return sortedData
    }
}

重构成更小更专一的代码:

class RefactoredViewModel : ViewModel() {
    // ...

    private fun processData(data: List<DataItem>): List<ProcessedDataItem> {
        return data.filter(::filterData)
            .map(::transformData)
            .sortedByDescending(::sortData)
    }

    private fun filterData(item: DataItem): Boolean {
        return item.isActive && item.value > 10
    }

    private fun transformData(item: DataItem): ProcessedDataItem {
        return ProcessedDataItem(
            id = item.id,
            displayName = "${item.name} (${item.value})",
            important = item.value > 50
        )
    }

    private fun sortData(item: ProcessedDataItem): Boolean {
        return item.important
    }
}

在重构的例子中,我们将长的processData方法分解为更小、更专注的函数:filterData、transformData和sortData。这使得代码更易于理解、测试和维护。

5. 强耦合:

高度依赖彼此的类或组件可能会使修改或测试代码变得困难。通过设计具有良好定义接口和最小依赖关系的组件来实现松耦合。
例子:
使用Kotlin和Jetpack Compose,ViewModel和Composable函数之间存在强耦合。我们将使用StateFlow重构它以实现松耦合。
强耦合例子:

class TightCouplingViewModel : ViewModel() {
    val data = mutableStateOf(listOf<DataItem>())

    init {
        loadData()
    }

    private fun loadData() {
        // Load data...
        data.value = loadedData
    }
}

@Composable
fun TightCouplingExample(viewModel: TightCouplingViewModel) {
    val data = viewModel.data.value
    LazyColumn {
        items(data) { item ->
            // Display data item...
        }
    }
}

使用松散耦合进行重构:
更新 ViewModel 以使用 StateFlow:

import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

class LooseCouplingViewModel : ViewModel() {
    private val _data = MutableStateFlow(listOf<DataItem>())
    val data: StateFlow<List<DataItem>> = _data

    init {
        loadData()
    }

    private fun loadData() {
        // Load data...
        _data.value = loadedData
    }
}

更新 Composable 函数以观察来自 ViewModel 的数据:

import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue

@Composable
fun LooseCouplingExample(viewModel: LooseCouplingViewModel) {
    val data by viewModel.data.collectAsState()
    LazyColumn {
        items(data) { item ->
            // Display data item...
        }
    }
}

在重构的示例中,我们通过使用StateFlow来观察和响应ViewModel中数据的变化,实现了ViewModel和Composable函数之间的松耦合。这种方法使得修改或测试代码更容易,因为ViewModel和UI组件不会直接引用彼此。

结论

总之,在Android开发中解决五大代码坏味道有助于创建更清晰、更高效、更高质量的代码库。通过遵循Jetpack Compose UI和MVVM架构的最佳实践,开发人员可以创建具有模块化、可维护和可测试性的应用程序。

  1. 通过将大型类分解为更小、更集中的功能单元,实现避免过多使用god对象,并实现存储库模式。
  2. 通过组合取代深层继承层次结构,创建更小、可重用的可组合项或混合项,以实现所需的功能。
  3. 通过将硬编码的值或“神奇数字”替换为常量或资源文件,使代码更具灵活性和可维护性。
  4. 通过将长方法或类分解为更小、更集中的功能单元,使其更易于理解、测试和维护。
  5. 通过设计具有良好定义接口和最小依赖关系的组件、使用LiveData或StateFlow来观察和响应ViewModel中的数据变化,并避免ViewModel和UI组件之间的直接引用,实现松耦合。
    通过解决这些代码坏味道,您可以增强开发过程,改善可维护性,并创建提供优秀用户体验的Android应用程序。

参考

https://medium.com/@fauzisho/top-5-code-smells-in-android-development-jetpack-compose-ui-and-mvvm-e3934ddbc14c文章来源地址https://www.toymoban.com/news/detail-434018.html

到了这里,关于Android开发中的前五个代码异味:Jetpack Compose UI和MVVM的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 对于Android开发,我们为何要学Jetpack Compose?

    Jetpack Compose 是用于构建原生 Android 界面的新工具包。它可简化并加快 Android 上的界面开发,使用更少的代码、强大的工具和直观的 Kotlin API,快速让应用生动而精彩。Compose 使用全新的组件——可组合项 (Composable) 来布局界面,使用修饰符 (Modifier) 来配置可组合项。 为何Jetp

    2024年02月10日
    浏览(30)
  • 编程之道:【代码重构】消除异味和坏味道,提升代码质量

    在软件开发中,有时会遇到一些让人不爽的情况,代码也不例外。这些情况被称为“代码异味”或“坏味道”。它们可能表明代码存在问题,需要进行重构以提升质量和可维护性。本文将介绍代码异味和坏味道是什么,以及如何识别和解决它们。 代码异味和坏味道是什么?

    2024年02月10日
    浏览(31)
  • Android使用Jetpack WindowManager来开发可折叠设备的探索

    我们在Google开发者大会上,看到Jetpack WindowManager和WindowSizeClass这些技术,如下图。 那这里不得不说折叠屏手机了 在其中一个显示区域中运行一个应用。 同时运行两个应用,各位于一个显示区域中(在 multi-window 模式下)。 可折叠设备还支持不同的折叠状态。折叠状态可用来

    2024年02月08日
    浏览(32)
  • Android NDK开发详解之编写C/C++代码中的Android SDK 版本属性)

    本部分将讨论如何使用 NDK 提供的库。 注意:有关导入预构建库(未包含在 NDK 中的库)的指南已移至各个构建系统的相关部分。请根据您的项目需求参阅 CMake 或 ndk-build 指南。 文中说明了 NDK 提供的 C ++ 运行时,并介绍了 NDK 提供的其他库(例如 OpenGL ES 和 OpenSL ES)以及支持

    2024年02月07日
    浏览(41)
  • Jetpack:021-Jetpack中的滑动列表

    我们在上一章回中介绍了Jetpack中底部导航栏相关的内容,本章回中主要介绍 滑动列表 。闲话休提,让我们一起Talk Android Jetpack吧! 我们先看一个场景:大家在使用手机时会打开联系人查找某位朋友,由于联系人比较多需要上下滑动才可以找到这位朋友,显示这么多联系人的

    2024年02月08日
    浏览(29)
  • Jetpack:025-Jetpack中的多点触控事件

    我们在上一章回中介绍了Jetpack中滚动事件相关的内容,本章回中主要介绍 多点解控事件 。闲话休提,让我们一起Talk Android Jetpack吧! 我们在本章回中介绍的多点触控事件是指通过多个手指同时操作,此时会发出相关的事件,这些事件包含, 缩放,旋转和平移 。常见的使用

    2024年02月06日
    浏览(29)
  • Android Jetpack Compose 别裁

    一、简介 二、compose优缺点 三、compose好学吗 四、Android Jetpack Compose 跟 fluter 哪个更好 五、Android Jetpack Compose 跟 fluter 技能学习选择 之所以叫Android Jetpack Compose别裁是希望能取舍网上的对compose的资料,推出别出心裁的文章,文章结束都会有一个案例,通过实践学习,让学习的

    2024年02月03日
    浏览(45)
  • Android之简单描述jetpack

    把很多变量,逻辑和数据摆在我们的Activity和Fragment中,这样的代码很混乱,难以维护。 这样的开发模式违反了单一责任的原则。 而ViewModel可以有效地划分责任。 具体的可以用于持有和UI元素相关的数据 ,以保证这些数据在屏幕旋转时不会丢失,以及负责和仓库之间进行通讯

    2023年04月20日
    浏览(29)
  • Jetpack Compose: Hello Android

    Jetpack Compose 是一个现代化的工具包,用于使用声明式方法构建原生 Android UI。在本博文中,我们将深入了解一个基本的 “Hello Android” 示例,以帮助您开始使用 Jetpack Compose。我们将探讨所提供代码片段中使用的函数和注解。 在深入代码之前,请确保您已经准备好使用 Jetpac

    2024年03月10日
    浏览(43)
  • Android Jetpack学习系列——Navigation

    写在前面 Google在2018年就推出了Jetpack组件库,但是直到今天我才给重视起来,这真的不得不说是一件让人遗憾的事。过去几年的空闲时间里,我一直在尝试做一套自己的组件库,帮助自己快速开发,虽然也听说过Jetpack,但是压根儿也没去了解,但是其实自己已经无形之中用到

    2024年02月02日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包