<LinearLayout
…
tools:viewBindingIgnore=“true” >
…
3.2 创建绑定类
有三个创建绑定类的 API:
fun bind(view : View) : T
fun inflate(inflater : LayoutInflater) : T
fun inflate(inflater : LayoutInflater, parent : ViewGroup?, attachToParent : Boolean) : T
- 1、在 Activity 中使用
MainActivity.kt
class TestActivity: AppCompatActivity(R.layout.activity_test) {
private lateinit var binding: ActivityTestBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTestBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.tvDisplay.text = “Hello World.”
}
}
- 2、在 Fragment 中使用
TestFragment.kt
class TestFragment : Fragment(R.layout.fragment_test) {
private var _binding: FragmentTestBinding? = null
private val binding get() = _binding!!
override fun onViewCreated(root: View, savedInstanceState: Bundle?) {
_binding = FragmentTestBinding.bind(root)
binding.tvDisplay.text = “Hello World.”
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
3.3 避免内存泄露
这里有一个隐藏的内存泄露问题,你需要理解清楚(严格来说这并不是 ViewBinding 的问题,即使你采用其它视图绑定方案也要考虑这个问题)。
问题:为什么 Fragment#onDestroyView() 里需要置空绑定类对象,而 Activity 里不需要? 答:Activity 实例和 Activity 视图的生命周期是同步的,而 Fragment 实例和 Fragment 视图的生命周期并不是完全同步的,因此需要在 Fragment 视图销毁时,手动回收绑定类对象,否则造成内存泄露。例如:detach Fragment,或者 remove Fragment 并且事务进入返回栈,此时 Fragment 视图销毁但 Fragment 实例存在。关于 Fragment 生命周期和事务在我之前的一篇文章里讨论过:Android | Fragment 核心原理 & 面试题 (AndroidX 版本)
总之,在视图销毁但是控制类对象实例还存活的时机,你就需要手动回收绑定类对象,否则造成内存泄露。
3.4 ViewBinding 绑定类源码
反编译如下:
public final class ActivityTestBinding implements ViewBinding {
private final ConstraintLayout rootView;
public final TextView tvDisplay;
private ActivityTestBinding (ConstraintLayout paramConstraintLayout1, TextView paramTextView)
this.rootView = paramConstraintLayout1;
this.tvDisplay = paramTextView;
}
public static ActivityTestBinding bind(View paramView) {
TextView localTextView = (TextView)paramView.findViewById(2131165363);
if (localTextView != null) {
return new ActivityMainBinding((ConstraintLayout)paramView, localTextView);
}else {
paramView = “tvDisplay”;
}
throw new NullPointerException("Missing required view with ID: ".concat(paramView));