3

我发现自己为我创建的每个新片段编写样板代码。这包括设置视图模型和视图绑定,这是我的代码中不相互依赖的两个不同部分,因此其中一个的解决方案仍然很棒。

片段代码示例:

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()
4

1 回答 1

8

正如在ViewModel 文档页面上看到的那样,Kotlin 代码不应该使用ViewModelProvider(this),而应该使用by viewModels()which 是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
    }
}

您可以遵循这样的方法,完全避免坚持绑定。这种方法意味着您的片段将是:

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 行共享代码,所有这些都是不同的,因此尝试构建一个基本片段并处理泛型将使事情变得更加复杂,这将是我不会建议。

于 2020-04-18T01:41:00.010 回答