我可以消除 Android 片段中的视图模型和视图绑定样板代码吗?
Can I eliminiate viewmodel and viewbinding boilerplate code in my Android Fragments?
我发现自己为我创建的每个新片段编写样板代码。
这包括设置 viewmodel 和 viewbinding,这是我的代码的两个不同部分,彼此不依赖,因此其中一个的解决方案仍然很棒。
片段代码示例:
class MyFragment : Fragment() {
// View binding
private var _binding: FragmentMyBinding? = null
// View model
private lateinit var model : MyViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Model init
model = ViewModelProvider(this).get(MyViewModel::class.java)
//binding init
_binding = FragmentMyBinding.inflate(inflater, container, false)
return _binding!!.root
}
}
class MyViewModel : ViewModel()
正如 ViewModel documentation page, Kotlin code should not use ViewModelProvider(this)
, but instead use by viewModels()
上所见,它是 fragment-ktx
依赖项的一部分。这取代了 lateinit var model
用法并且必须在 onCreateView()
中执行任何操作,这意味着您的片段变为:
class MyFragment : Fragment() {
// View binding
private var _binding: FragmentMyBinding? = null
// View model
private val model: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//binding init
_binding = FragmentMyBinding.inflate(inflater, container, false)
return _binding!!.root
}
}
您可以采用 this one 之类的方法,完全避免绑定。这种方法意味着您的片段将是:
class MyFragment : Fragment(R.layout.my_fragment) {
// View model
private val model: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val binding = FragmentMyBinding.bind(view)
// Now use the binding and your ViewModel
}
}
另一种选择是将 AutoClearedValue
复制到您的项目中并使用它,这会使它看起来像:
class MyFragment : Fragment() {
// View binding
private var binding by autoCleared<FragmentMyBinding>()
// View model
private val model: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMyBinding.inflate(inflater, container, false)
// Now use the binding and your ViewModel
return binding.root
}
}
此时,无论使用哪种解决方案,您都最多使用 3 行共享代码,所有这些代码行都不相同,因此尝试构建基本片段并处理泛型会使事情变得更加复杂。我不会建议这样做。
我发现自己为我创建的每个新片段编写样板代码。 这包括设置 viewmodel 和 viewbinding,这是我的代码的两个不同部分,彼此不依赖,因此其中一个的解决方案仍然很棒。
片段代码示例:
class MyFragment : Fragment() {
// View binding
private var _binding: FragmentMyBinding? = null
// View model
private lateinit var model : MyViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Model init
model = ViewModelProvider(this).get(MyViewModel::class.java)
//binding init
_binding = FragmentMyBinding.inflate(inflater, container, false)
return _binding!!.root
}
}
class MyViewModel : ViewModel()
正如 ViewModel documentation page, Kotlin code should not use ViewModelProvider(this)
, but instead use by viewModels()
上所见,它是 fragment-ktx
依赖项的一部分。这取代了 lateinit var model
用法并且必须在 onCreateView()
中执行任何操作,这意味着您的片段变为:
class MyFragment : Fragment() {
// View binding
private var _binding: FragmentMyBinding? = null
// View model
private val model: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//binding init
_binding = FragmentMyBinding.inflate(inflater, container, false)
return _binding!!.root
}
}
您可以采用 this one 之类的方法,完全避免绑定。这种方法意味着您的片段将是:
class MyFragment : Fragment(R.layout.my_fragment) {
// View model
private val model: MyViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val binding = FragmentMyBinding.bind(view)
// Now use the binding and your ViewModel
}
}
另一种选择是将 AutoClearedValue
复制到您的项目中并使用它,这会使它看起来像:
class MyFragment : Fragment() {
// View binding
private var binding by autoCleared<FragmentMyBinding>()
// View model
private val model: MyViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMyBinding.inflate(inflater, container, false)
// Now use the binding and your ViewModel
return binding.root
}
}
此时,无论使用哪种解决方案,您都最多使用 3 行共享代码,所有这些代码行都不相同,因此尝试构建基本片段并处理泛型会使事情变得更加复杂。我不会建议这样做。