目录
概要
优化思路
一、重构过长的Activity
二、优化臃肿的ViewModel
示例代码:
1.Activity封装到单独的Fragment中
2.把ViewModel拆分成多个子viewmodel
小结
概要
在大型项目中,随着项目越做越大,activity和viewmodel的代码会越来越多,尽量保持Activity和ViewModel的代码精简和易于维护是非常重要的。个人建议700行以上就应该考虑,尽量让代码控制在1000行以内。
不然随着代码多维护起来困难,代码混乱,有bug时定位问题难,增加需求代码难等问题就会随之而来,那应该怎么办呢?
优化思路
一、重构过长的Activity
- 功能拆分:如果
Activity
承载了多个不同功能区域的UI,可以考虑将每个区域封装到单独的Fragment
或子Activity中。这样可以将每个功能区域的逻辑和UI代码分开,使Activity
更加简洁。 - 提取组件:将重复的UI元素或逻辑封装成自定义View或辅助类,减少Activity的体积。
- 职责分离:确保
Activity
只处理与UI生命周期相关的事件和逻辑。将业务逻辑和数据处理移至ViewModel
。 - 接口封装:设计接口来隔离Activity与其他层(如数据层)的直接交互,降低耦合度。
- 提取工具类和辅助类:如果
Activity
中有一些公共的、可重用的代码片段,可以将其提取到单独的工具类或辅助类中,并在Activity
中通过调用这些方法来实现功能。
二、优化臃肿的ViewModel
- 数据抽象:将数据处理逻辑放到专门的Model层或Repository层,ViewModel仅负责协调和触发数据更新。
- 状态管理:使用StateFlow或其他状态管理库来简化状态的持有和更新,避免手动管理大量状态变量。
- 多用LiveData:利用LiveData的观察者模式自动管理数据的生命周期,减少在ViewModel中的生命周期处理代码。
- 逻辑外包:将业务处理逻辑外包给专门的用例类(Use Case Classes)或领域服务(Domain Services)。
- 作用域限定:限定ViewModel的作用范围,例如使用Navigation的Scoped ViewModel,确保ViewModel只在需要的屏幕中使用。
-
数据拆分:如果
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: FragmentManageroverride 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>> = _usersfun 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> = _userfun setUser(user: User) {_user.value = user}
}
最后,在Activity或Fragment中,将这两个ViewModel关联起来:
class UserListActivity : AppCompatActivity() {private lateinit var userListViewModel: UserListViewModelprivate lateinit var userDetailViewModel: UserDetailViewModeloverride 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,分别处理用户列表页面和用户详情页面的业务逻辑。
小结
- 拆分功能:将大型类拆分为多个小类,每个类负责一个特定的功能或职责。
-
代码审查(Code Review):定期进行团队内部代码审查,发现并修复代码中的冗余和不良编码习惯。
- 使用扩展函数:将activity或者ViewModel的一些逻辑封装为扩展函数。
- 使用辅助类:创建辅助类来处理activity或者ViewModel中的某些逻辑。
- 使用委托:使用Kotlin的
by
关键字委托给其他对象。(可以看另一篇关于委托的介绍:kotlin——委托(使用委托类来实现多继承)、使用委托类来创建viewmodel实例、内部类实现多继承、使用委托把activity的部分职责代码分离出来_kotlin 多继承-CSDN博客)