kotlin——MVVM框架下的大型项目优化、以及activity和viewmodel臃肿的优化

发布于:2024-06-26 ⋅ 阅读:(55) ⋅ 点赞:(0)

概要

在大型项目中,随着项目越做越大,activity和viewmodel的代码会越来越多,尽量保持Activity和ViewModel的代码精简和易于维护是非常重要的。个人建议700行以上就应该考虑,尽量让代码控制在1000行以内。

不然随着代码多维护起来困难,代码混乱,有bug时定位问题难,增加需求代码难等问题就会随之而来,那应该怎么办呢?

优化思路

一、重构过长的Activity

  1. 功能拆分:如果Activity承载了多个不同功能区域的UI,可以考虑将每个区域封装到单独的Fragment或子Activity中。这样可以将每个功能区域的逻辑和UI代码分开,使Activity更加简洁。
  2. 提取组件:将重复的UI元素或逻辑封装成自定义View或辅助类,减少Activity的体积。
  3. 职责分离:确保Activity只处理与UI生命周期相关的事件和逻辑。将业务逻辑和数据处理移至ViewModel
  4. 接口封装:设计接口来隔离Activity与其他层(如数据层)的直接交互,降低耦合度。
  5. 提取工具类和辅助类:如果Activity中有一些公共的、可重用的代码片段,可以将其提取到单独的工具类或辅助类中,并在Activity中通过调用这些方法来实现功能。

二、优化臃肿的ViewModel

  1. 数据抽象:将数据处理逻辑放到专门的Model层或Repository层,ViewModel仅负责协调和触发数据更新。
  2. 状态管理:使用StateFlow或其他状态管理库来简化状态的持有和更新,避免手动管理大量状态变量。
  3. 多用LiveData:利用LiveData的观察者模式自动管理数据的生命周期,减少在ViewModel中的生命周期处理代码。
  4. 逻辑外包:将业务处理逻辑外包给专门的用例类(Use Case Classes)或领域服务(Domain Services)。
  5. 作用域限定:限定ViewModel的作用范围,例如使用Navigation的Scoped ViewModel,确保ViewModel只在需要的屏幕中使用。
  6. 数据拆分:如果ViewModel中处理的数据过多,可以考虑将其拆分为多个小的ViewModel,每个ViewModel只处理一部分数据。这样可以使每个ViewModel更加专注和易于理解。

示例代码:

1.Activity封装到单独的Fragment中
// FirstFragment .kt
class FirstFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_a, container, false)
    }
}

// SecondFragment .kt
class SecondFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_b, container, false)
    }
}
class MainActivity : AppCompatActivity() {
    private lateinit var fragmentManager: FragmentManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fragmentManager = supportFragmentManager

        // 添加第一个区域
        addFragment(FirstFragment())

        // 添加第二个区域
        addFragment(SecondFragment())
    }

    private fun addFragment(fragment: Fragment) {
        val transaction: FragmentTransaction = fragmentManager.beginTransaction()
        transaction.add(R.id.fragment_container, fragment)
        transaction.commit()
    }
}
2.把ViewModel拆分成多个子viewmodel

假设我们有一个应用,它有两个页面:用户列表页面和用户详情页面。我们可以将这两个页面的业务逻辑分别放在两个ViewModel中。

首先,创建一个UserListViewModel,用于处理用户列表页面的逻辑:

class UserListViewModel : ViewModel() {
    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users

    fun fetchUsers() {
        // 模拟从网络或数据库获取用户列表
        val userList = listOf(
            User("张三", 25),
            User("李四", 30),
            User("王五", 35)
        )
        _users.value = userList
    }
}

然后,创建一个UserDetailViewModel,用于处理用户详情页面的逻辑:

class UserDetailViewModel : ViewModel() {
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> = _user

    fun setUser(user: User) {
        _user.value = user
    }
}

最后,在Activity或Fragment中,将这两个ViewModel关联起来:

class UserListActivity : AppCompatActivity() {
    private lateinit var userListViewModel: UserListViewModel
    private lateinit var userDetailViewModel: UserDetailViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user_list)

        userListViewModel = ViewModelProvider(this).get(UserListViewModel::class.java)
        userDetailViewModel = ViewModelProvider(this).get(UserDetailViewModel::class.java)

        userListViewModel.users.observe(this, Observer { users ->
            // 更新用户列表UI
        })

        // 当点击用户时,设置用户详情ViewModel的数据并跳转到用户详情页面
        userListView.setOnItemClickListener { parent, view, position, id ->
            val selectedUser = users[position]
            userDetailViewModel.setUser(selectedUser)
            startActivity(Intent(this, UserDetailActivity::class.java))
        }
    }
}

这样,我们就将原本一个大的ViewModel拆分成了两个小的ViewModel,分别处理用户列表页面和用户详情页面的业务逻辑。

小结

  1. 拆分功能:将大型类拆分为多个小类,每个类负责一个特定的功能或职责。
  2. 代码审查(Code Review):定期进行团队内部代码审查,发现并修复代码中的冗余和不良编码习惯。

  3. 使用扩展函数:将activity或者ViewModel的一些逻辑封装为扩展函数。
  4. 使用辅助类:创建辅助类来处理activity或者ViewModel中的某些逻辑。
  5. 使用委托:使用Kotlin的by关键字委托给其他对象。(可以看另一篇关于委托的介绍:kotlin——委托(使用委托类来实现多继承)、使用委托类来创建viewmodel实例、内部类实现多继承、使用委托把activity的部分职责代码分离出来_kotlin 多继承-CSDN博客

网站公告

今日签到

点亮在社区的每一天
去签到