📜  在Android Jetpack中查看带有片段的绑定

📅  最后修改于: 2021-05-08 20:47:43             🧑  作者: Mango

在上一篇文章Android Jetpack中的View Binding中,已经讨论了为什么在Android项目中获得ViewBinding功能会带来很多好处。但是,当涉及到带有片段的ViewBinding时,情况就会发生变化。因为Fragment的生命周期不同,而Activity的生命周期也不同,所以这里的内容也与上述文章中讨论的相同,片段布局的命名约定更改为Pascal大小写,而片段布局的属性更改为驼峰大小写。例如, fragment1.xml-> Fragment1Binding片段布局下的edit_text (id)更改为eEditText (驼峰式),因此在本文中,我们将使用Fragments讨论ViewBinding。下面提供了一个示例视频,以使您对我们在本文中将要做的事情有个大概的了解。请注意,我们将使用Kotlin语言实施此项目。

分步实施

步骤1:创建一个新的空活动项目

  • 使用Android Studio创建一个空的Activity Android Studio项目。参考Android |如何在Android Studio中创建/启动新项目?

步骤2:启用ViewBinding功能

  • 通过在应用程序级别的build.gradle文件中调用以下代码段来启用ViewBinding功能,然后单击右上角出现的“立即同步”按钮。
  • 如果无法找到应用程序级build.gradle文件,则请参考下图。调用上述构建功能。

步骤3:使用activity_main.xml文件

  • 活动的主要布局包含两个按钮,用于切换片段1和片段2,以及一个Framelayout,用于将片段保存在CardView中。还有一个“提交”按钮,用于检查何时按下时提交了其片段的数据。
  • 要实现相同的功能,请在activity_main.xml文件中调用以下代码。
XML


  
    


XML



  
    
  
    
  
    


XML



  
    
  
    
  
    


Kotlin
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
  
// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment1Binding
  
class ExampleFragment1 : Fragment() {
  
    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be set to null
    private var _binding: Fragment1Binding? = null
  
    // with the backing property of the kotlin we extract
    // the non null value of the _binding
    private val binding get() = _binding!!
  
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
  
        // inflate the layout and bind to the _binding
        _binding = Fragment1Binding.inflate(inflater, container, false)
  
        // retrieve the entered data by the user
        binding.doneButton1.setOnClickListener {
            val str: String = binding.editText1.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }
  
        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 1", Toast.LENGTH_SHORT).show()
        }
  
        // Inflate the layout for this fragment
        return binding.root
    }
  
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}


Kotlin
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
  
// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment2Binding
  
class ExampleFragment2 : Fragment() {
  
    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be 
    // set to null
    private var _binding: Fragment2Binding? = null
  
    // with the backing property of the kotlin
    // we extract
    // the non null value of the _binding
    private val binding get() = _binding!!
  
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
  
        // inflate the layout and bind to the _binding
        _binding = Fragment2Binding.inflate(inflater, container, false)
  
        // retrieve the entered data by the user
        binding.doneButton2.setOnClickListener {
            val str: String = binding.editText2.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }
  
        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 2", Toast.LENGTH_SHORT).show()
        }
  
        // Inflate the layout for this fragment
        return binding.root
    }
  
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}


Kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.adityamshidlyali.gfgarticle.databinding.ActivityMainBinding
  
class MainActivity : AppCompatActivity() {
  
    // create binding instance for the activity_main.xml
    private lateinit var binding: ActivityMainBinding
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        // when app is initially opened the Fragment 1 should be visible
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, ExampleFragment1())
            addToBackStack(null)
            commit()
        }
  
        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment1B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }
  
        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment2B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }
    }
  
    // function to change the fragment which is used to reduce the lines of code
    private fun changeFragment(fragmentToChange: Fragment): Unit {
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, fragmentToChange)
            addToBackStack(null)
            commit()
        }
    }
}


输出界面:

步骤4:创建两个片段

  • 创建两个片段,其中包括表示片段编号编辑文本的文本视图和一个按钮。要实现每个片段的UI,您可以参考以下代码。
  • 片段1:

XML格式




  
    
  
    
  
    
  • 片段2:

XML格式




  
    
  
    
  
    

步骤5:使用Fragments.kt文件

  • 首先,可为空的绑定变量最初被分配为null,并且当片段的视图被破坏时,必须再次将其设置为null(在本例中为_binding )。
  • 为了避免对可为空的绑定对象进行null检查,通过使用kotlin的backing属性,我们制作了绑定变量的另一个副本(在本例中为binding )。
  • 但是,如果该片段想从主机活动访问视图,则可以使用findViewById()方法来完成。
  • 在每个片段的.kt文件中调用以下代码。添加了注释以便更好地理解。
  • 片段1:

科特林

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
  
// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment1Binding
  
class ExampleFragment1 : Fragment() {
  
    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be set to null
    private var _binding: Fragment1Binding? = null
  
    // with the backing property of the kotlin we extract
    // the non null value of the _binding
    private val binding get() = _binding!!
  
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
  
        // inflate the layout and bind to the _binding
        _binding = Fragment1Binding.inflate(inflater, container, false)
  
        // retrieve the entered data by the user
        binding.doneButton1.setOnClickListener {
            val str: String = binding.editText1.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }
  
        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 1", Toast.LENGTH_SHORT).show()
        }
  
        // Inflate the layout for this fragment
        return binding.root
    }
  
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
  • 片段2:

科特林

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.fragment.app.Fragment
  
// Enter your package name here
import com.adityamshidlyali.gfgarticle.databinding.Fragment2Binding
  
class ExampleFragment2 : Fragment() {
  
    // assign the _binding variable initially to null and
    // also when the view is destroyed again it has to be 
    // set to null
    private var _binding: Fragment2Binding? = null
  
    // with the backing property of the kotlin
    // we extract
    // the non null value of the _binding
    private val binding get() = _binding!!
  
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
  
        // inflate the layout and bind to the _binding
        _binding = Fragment2Binding.inflate(inflater, container, false)
  
        // retrieve the entered data by the user
        binding.doneButton2.setOnClickListener {
            val str: String = binding.editText2.text.toString()
            if (str.isNotEmpty()) {
                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()
            }
        }
  
        // handle the button from the host activity using findViewById method
        val submitButton: Button = activity!!.findViewById(R.id.submit_button)
        submitButton.setOnClickListener {
            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 2", Toast.LENGTH_SHORT).show()
        }
  
        // Inflate the layout for this fragment
        return binding.root
    }
  
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

步骤6:使用MainActivity.kt文件

  • MainActivity.kt文件中,仅实现了片段的事务功能。请参阅以下代码及其输出,以更好地理解。

科特林

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.adityamshidlyali.gfgarticle.databinding.ActivityMainBinding
  
class MainActivity : AppCompatActivity() {
  
    // create binding instance for the activity_main.xml
    private lateinit var binding: ActivityMainBinding
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        // when app is initially opened the Fragment 1 should be visible
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, ExampleFragment1())
            addToBackStack(null)
            commit()
        }
  
        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment1B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }
  
        // handle the fragment 2 button to toggle the fragment 2
        binding.fragment2B.setOnClickListener {
            changeFragment(ExampleFragment1())
        }
    }
  
    // function to change the fragment which is used to reduce the lines of code
    private fun changeFragment(fragmentToChange: Fragment): Unit {
        supportFragmentManager.beginTransaction().apply {
            replace(binding.fragmentHolder.id, fragmentToChange)
            addToBackStack(null)
            commit()
        }
    }
}

输出:

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处前往由我们的专家精心策划的指南,以使您立即做好行业准备!