具有视图绑定的 BaseFragment
BaseFragment with viewbinding
要在 android 应用程序中使用 viewbinding
我基本上是为 Activity
和 Fragment
创建基础 类 以删除每次编写充气代码的样板.
ACTIVITY:
BaseActivity
与 viewbinding
:
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = getViewBinding()
}
abstract fun getViewBinding(): VB
}
MainActivity
:
class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
//we can directly use binding now and it works fine inside activity
//binding.view.doSomething()
}
override fun getViewBinding(): ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
}
碎片 :
BaseFragment
:
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
var binding: VB? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = getViewBinding(view)
}
abstract fun getViewBinding(view: View): VB
}
DemoFragment
:
class DemoFragment : BaseFragment<DemoFragmentBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//problem is here
binding.txtData.text="Something"
}
override fun getViewBinding(view: View): DemoFragmentBinding = DemoFragmentBinding.bind(view)
}
demo_fragment.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragments.DemoFragment">
<TextView
android:id="@+id/txt_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello" />
</FrameLayout>
Problem : Unable to access views using binding inside Demofragment. I don't know why it works with activity and not with fragment.
2nd way that I don't want todo:
实施'androidx.fragment:fragment-ktx:1.3.1'
class DemoFragment : Fragment(R.layout.demo_fragment) {
lateinit var binding: DemoFragmentBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DemoFragmentBinding.bind(view).apply {
txtData.text = "Hello World"
}
}
}
我查看了文档,我不确定这是否会破坏您对 BaseFragment
中抽象模式的要求,但我使用此更改测试了您的代码并且它有效。唯一的变化是 DemoFragment
:
//Add this for the onCreateView implementation
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DemoFragmentBinding.inflate(LayoutInflater.from(context), null, false)
val view = binding!!.root
return view
}
然后我在onViewCreated
测试:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//problem is here
binding?.txtData?.text="Something"
}
它奏效了。我查看的文档是 this section
我认为这样做仍然可以避免一些样板代码,但是 onCreateView
覆盖对于每个片段都是必需的,因为不同的视图绑定 inflation(例如 DemoFragmentBinding.inflate etc etc
)
您需要覆盖 BaseFragment 中的 onCreateView
并初始化视图绑定
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = getViewBinding()
return binding.root
}
然后改变这一行
override fun getViewBinding(view: View): DemoFragmentBinding = DemoFragmentBinding.bind(view)
和
override fun getViewBinding() = DemoFragmentBinding.inflate(layoutInflater)
基础片段:
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
private var _binding: VB? = null
val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = getViewBinding()
return binding.root
}
abstract fun getViewBinding(): VB
}
DemoFragment:
class DemoFragment : BaseFragment<DemoFragmentBinding>() {
override fun getViewBinding() = DemoFragmentBinding.inflate(layoutInflater)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.apply {
txtData.text = "Something"
}
}
}
这里是实现此 factory abstraction with ViewBinding
. I am sharing the implementation code below. I am using genrics
的另一种方法。如果有人需要进一步解释,我在这里。确保您已经在 build.gradle
文件中启用了 viewbinding
功能。然后使用以下 BaseFragment.kt
作为您的片段抽象。
基础片段:
typealias Inflate<T> = (LayoutInflater, ViewGroup?, Boolean) -> T
abstract class BaseFragment<V: ViewBinding>(
private val inflate: Inflate<V>
) : Fragment() {
private lateinit var _binding: V
val binding get() = _binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = inflate(inflater, container, false)
return binding.root
}
}
N:B:了解更多 typealias。
主页片段:
// Implement the BaseFragment like below
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// usages by calling public variable 'binding' from base class
binding.message.text = "update $value"
}
}
使用https://github.com/hoc081098/ViewBindingDelegate
abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragment(layoutId) {
protected abstract val binding: VB
}
import com.hoc081098.viewbindingdelegate.*
class MainFragment: BaseFragment<FragmentMainBinding>(R.layout.fragment_main) {
override val binding by viewBinding()
}
要在 android 应用程序中使用 viewbinding
我基本上是为 Activity
和 Fragment
创建基础 类 以删除每次编写充气代码的样板.
ACTIVITY:
BaseActivity
与 viewbinding
:
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = getViewBinding()
}
abstract fun getViewBinding(): VB
}
MainActivity
:
class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
//we can directly use binding now and it works fine inside activity
//binding.view.doSomething()
}
override fun getViewBinding(): ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
}
碎片 :
BaseFragment
:
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
var binding: VB? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = getViewBinding(view)
}
abstract fun getViewBinding(view: View): VB
}
DemoFragment
:
class DemoFragment : BaseFragment<DemoFragmentBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//problem is here
binding.txtData.text="Something"
}
override fun getViewBinding(view: View): DemoFragmentBinding = DemoFragmentBinding.bind(view)
}
demo_fragment.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.fragments.DemoFragment">
<TextView
android:id="@+id/txt_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello" />
</FrameLayout>
Problem : Unable to access views using binding inside Demofragment. I don't know why it works with activity and not with fragment.
2nd way that I don't want todo:
实施'androidx.fragment:fragment-ktx:1.3.1'
class DemoFragment : Fragment(R.layout.demo_fragment) {
lateinit var binding: DemoFragmentBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DemoFragmentBinding.bind(view).apply {
txtData.text = "Hello World"
}
}
}
我查看了文档,我不确定这是否会破坏您对 BaseFragment
中抽象模式的要求,但我使用此更改测试了您的代码并且它有效。唯一的变化是 DemoFragment
:
//Add this for the onCreateView implementation
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DemoFragmentBinding.inflate(LayoutInflater.from(context), null, false)
val view = binding!!.root
return view
}
然后我在onViewCreated
测试:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//problem is here
binding?.txtData?.text="Something"
}
它奏效了。我查看的文档是 this section
我认为这样做仍然可以避免一些样板代码,但是 onCreateView
覆盖对于每个片段都是必需的,因为不同的视图绑定 inflation(例如 DemoFragmentBinding.inflate etc etc
)
您需要覆盖 BaseFragment 中的 onCreateView
并初始化视图绑定
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = getViewBinding()
return binding.root
}
然后改变这一行
override fun getViewBinding(view: View): DemoFragmentBinding = DemoFragmentBinding.bind(view)
和
override fun getViewBinding() = DemoFragmentBinding.inflate(layoutInflater)
基础片段:
abstract class BaseFragment<VB : ViewBinding> : Fragment() {
private var _binding: VB? = null
val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = getViewBinding()
return binding.root
}
abstract fun getViewBinding(): VB
}
DemoFragment:
class DemoFragment : BaseFragment<DemoFragmentBinding>() {
override fun getViewBinding() = DemoFragmentBinding.inflate(layoutInflater)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.apply {
txtData.text = "Something"
}
}
}
这里是实现此 factory abstraction with ViewBinding
. I am sharing the implementation code below. I am using genrics
的另一种方法。如果有人需要进一步解释,我在这里。确保您已经在 build.gradle
文件中启用了 viewbinding
功能。然后使用以下 BaseFragment.kt
作为您的片段抽象。
基础片段:
typealias Inflate<T> = (LayoutInflater, ViewGroup?, Boolean) -> T
abstract class BaseFragment<V: ViewBinding>(
private val inflate: Inflate<V>
) : Fragment() {
private lateinit var _binding: V
val binding get() = _binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = inflate(inflater, container, false)
return binding.root
}
}
N:B:了解更多 typealias。
主页片段:
// Implement the BaseFragment like below
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// usages by calling public variable 'binding' from base class
binding.message.text = "update $value"
}
}
使用https://github.com/hoc081098/ViewBindingDelegate
abstract class BaseFragment<VB : ViewBinding>(@LayoutRes layoutId: Int) : Fragment(layoutId) {
protected abstract val binding: VB
}
import com.hoc081098.viewbindingdelegate.*
class MainFragment: BaseFragment<FragmentMainBinding>(R.layout.fragment_main) {
override val binding by viewBinding()
}