如何正确使用ViewBinding创建父fragment?

问题描述 投票:0回答:1

我有大约 15 个片段,大部分使用相同的代码,我还为 ViewBinding 创建了一个有效的 BaseFragment,这样我就不需要每次都编写该部分。 然而,还有其他函数在所有片段上重复,但它们利用每个片段的视图(在所有片段上都是相同的),但我一生都找不到如何正确引用它们或在 BaseFragment 中设置它们.

这是我当前的 BaseFragment:

abstract class BaseFragment<VB : ViewBinding> : Fragment() {

    private var _binding: VB? = null
    val binding: VB
        get() = _binding!!

    abstract fun inflateBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
        attachToRoot: Boolean
    ): VB

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = inflateBinding(inflater, container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    fun navigateToActivity(activityClass: Class<*>) {
        val intent = Intent(requireContext(), activityClass)
        startActivity(intent)
        requireActivity().finish()
    }
}

这是我想重新利用的每个片段上存在的功能之一:

private fun navButtons() {
        binding.btnExit.setOnClickListener {
            val currentTime = System.currentTimeMillis()
            if (currentTime - lastExitButtonClickTime < 2000) {
       
                navigateToActivity(IntroTreasurehuntersActivity::class.java)
            } else {
         
                Toast.makeText(context, "Press again to exit", Toast.LENGTH_SHORT).show()
                lastExitButtonClickTime = currentTime
            }
        }
    }

以防万一,这就是我对它们进行视图绑定的方式,我很确定这也可以更好:

class Treasurehuntersq2Fragment : BaseFragment<FragmentTreasurehuntersq2Binding>() {

    override fun inflateBinding(
        inflater: LayoutInflater,
        container: ViewGroup?,
        attachToRoot: Boolean
    ): FragmentTreasurehuntersq2Binding {
        return FragmentTreasurehuntersq2Binding.inflate(inflater, container, attachToRoot)
    }

现在,如果我简单地将该函数复制到 BaseFragment,当然它不起作用,因为那里不存在视图按钮“btnExit”。正确的做法是什么?

android xml kotlin inheritance android-viewbinding
1个回答
0
投票

对于ViewBinding Part,你可以在baseFragment中声明一个受保护的绑定属性,并让每个childFragment对其进行初始化。

为了处理导航事件,您可以考虑在所有片段之间使用 SharedViewModel,这样任何事件都会从片段发送到 viewModel,并从 BaseFragment 观察这些事件并相应地处理它们,这是一个示例解决方案。

abstract class BaseFragment<VB : ViewBinding> : Fragment() {

  protected lateinit var binding: VB

 override fun onViewCreated(
    view: View,
    savedInstanceState: Bundle?
) {
       observeNavigationState()
 }
 
 private fun observeNavigationState(){
     viewModel.NavigateToIntroTreasurehuntersActivity.observe(viewLifecycleOwner) { NavigateToIntroTreasurehuntersState -> ->
        if (NavigateToIntroTreasurehuntersState) {  // true i.e naviagtion is started
            val intent = Intent(
                requireActivity(),
                IntroTreasurehuntersActivity::class.java
            )   
            startActivity(intent)  
            requireActivity().finish()  


            viewModel.onNavigateToIntroTreasurehuntersActivityFinished()
        }
    }
 }

 

}

类 Treasurehuntersq2Fragment:BaseFragment() {

 override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {  

    binding = FragmentTreasurehuntersq2Binding.inflate(inflater)  

    return binding.root
}
 
  override fun onViewCreated(
    view: View,
    savedInstanceState: Bundle?
) {
      setListeners()
  }
  private fun setListeners(){
      binding.btnExit.setOnClickListener {
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastExitButtonClickTime < 2000) {
  
            viewModel.onNavigateToIntroTreasurehuntersActivityStarted()
        } else {
     
            Toast.makeText(context, "Press again to exit", Toast.LENGTH_SHORT).show()
            lastExitButtonClickTime = currentTime
        }
    }
  }

}

© www.soinside.com 2019 - 2024. All rights reserved.