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

概要

在大型项目中,随着项目越做越大,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. Model (Beans/Data)

    • 包含数据模型(如POJOs、数据实体)。
    • 例如:User.javaPost.java
  2. Repository

    • 负责与数据源(如数据库、网络API)交互。
    • 实现数据访问逻辑,可能是异步的。
    • 例如:UserRepository.javaPostRepository.java
  3. API/Network

    • 负责与远程服务(如REST API)通信。
    • 使用Retrofit、OkHttp等库。
    • 例如:UserService.javaRetrofitClient.java
  4. ViewModel

    • 持有UI相关的数据以及命令。
    • 处理与Repository的交互。
    • 使用LiveData、StateFlow或RxJava等响应式编程库来观察数据变化。
    • 例如:UserViewModel.javaPostViewModel.java
  5. UI (Activity/Fragment/Views)

    • 负责展示ViewModel中的数据。
    • 观察ViewModel中的数据变化并更新UI。
    • 例如:UserActivity.javaPostFragment.java
  6. Adapter

    • 用于在RecyclerView中展示列表数据。
    • 通常与Model层的数据模型一起使用。
    • 例如:UserListAdapter.java
  7. Utils/Helpers

    • 包含各种实用工具和辅助类。
    • 例如:DateHelper.javaNetworkHelper.java
  8. ViewModels/Factories (针对工厂模式)

    • 虽然不是标准的MVVM组件,但你可以为ViewModel创建工厂类来简化创建过程。
    • 例如:ViewModelFactory.java
  9. Strategies (针对策略模式)

    • 策略模式通常用于定义一系列可重用的算法,并使它们在运行时可以相互替换。
    • 在MVVM中,策略可能用于定义不同的数据处理逻辑或UI行为。
    • 例如:你可以有一个SortingStrategy接口,以及多个实现类(如AlphabeticalSortingStrategy.javaDateSortingStrategy.java),然后在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博客
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wy313622821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值