Google挖坑后人埋-ViewBinding(下),2024年最新Golang面试基础知识

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Golang全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注go)
img

正文

val type = javaClass.genericSuperclass
if (type is ParameterizedType) {
val clazz = type.actualTypeArguments[0] as Class
val method = clazz.getMethod(“inflate”, LayoutInflater::class.java)
binding = method.invoke(null, layoutInflater) as T
contentView = binding.root
}
}
}

这样我们的调用终于干净了。

class PocketSquareActivity : BaseBindingActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

binding.title.text = “XXX”
}
}

既然Activity这样可以,那么Fragment也同样的。

abstract class BaseBindingFragment : Fragment() {

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

@Suppress(“UNCHECKED_CAST”)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val type = javaClass.genericSuperclass
val clazz = (type as ParameterizedType).actualTypeArguments[0] as Class
val method = clazz.getMethod(“inflate”, LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
_binding = method.invoke(null, layoutInflater, container, false) as T
return binding.root
}

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

但是这个地方有个问题,那就是onDestroyView里面的释放,下面来继续简化。

abstract class BaseBindingFragment : Fragment() {

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

@Suppress(“UNCHECKED_CAST”)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val type = javaClass.genericSuperclass
val clazz = (type as ParameterizedType).actualTypeArguments[0] as Class
val method = clazz.getMethod(“inflate”, LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
_binding = method.invoke(null, layoutInflater, container, false) as T
this.viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
_binding = null
}
})
return binding.root
}
}

通过lifecycle,就可以把释放的代码也包在基类中了,这样Fragment和Activity的使用就基本类似了。

而对于RecyclerView来说,我觉得没太大必要封装,具体使用可以查看前一篇文章。

不使用基类

上面都是基于继承来实现的封装,这样的好处是可以尽可能的简化子类的代码调用,但是缺点呢就是造成了一定的代码侵入,所以,如果不使用继承基类的方式,可以借助Kotlin的委托来实现调用的简化。

对于Activity来说,前面已经实现了。

inline fun Activity.inflate() = lazy {
inflateViewBinding(layoutInflater).apply { setContentView(root) }
}

val binding by inflate()

而对于Fragment来说,稍微复杂一点,因为在Fragment里面inflate需要三个参数,和Activity不一样,特别是parent参数,不太好获取,所以这里可以使用bind来创建Binding,官网中也给出了这样的建议。

Note: The inflate() method requires you to pass in a layout inflater. If the layout has already been inflated, you can instead call the binding class’s static bind() method. To learn more, see an example from the view binding GitHub sample.

所以,我们可以这样来创建委托。

inline fun Fragment.inflate() = FragmentViewBindingDelegate(T::class.java)

class FragmentViewBindingDelegate(private val clazz: Class) : ReadOnlyProperty<Fragment, T> {
private var binding: T? = null

@Suppress(“UNCHECKED_CAST”)
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
if (binding == null) {
binding = clazz.getMethod(“bind”, View::class.java).invoke(null, thisRef.requireView()) as T
thisRef.viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
binding = null
}
})
}
return binding!!
}
}

使用方式和Activity一致。

这里实际上体现了Fragment的两种初始化Binding的方法,一种是在onCreateView中,一种是在onViewCreated中。

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

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = XXXXBinding.bind(view)
}

奇技淫巧

最近在medium上看到一种更有意思的封装方法,如果你能看懂这种方式,说明你对Kotlin的理解是比较深入的了。

首先,我们要了解Kotlin的「函数引用」。

在Kotlin中,通过::method这种方式,来将一个函数转为对象,转为对象之后,就可以当做参数进行传递了,这是一个很重要的高阶函数特性。我们可以把一个函数当做参数传递给另一个函数,这样在这个函数里面,就可以调用传进来的函数,从而——避免使用反射。

我们再回头看下前面的拓展函数,归根到底,我们实际上就是为了下面这个东西:

XXXLayoutBinding.inflate(layoutInflater)

这不就是XXXLayoutBinding的一个函数吗?所以我们可以借助函数引用,做下面的操作:

fun Activity.inflate(inflater: (LayoutInflater) -> T) = lazy {
inflater(layoutInflater).apply { setContentView(root) }
}

函数引用不支持inline操作

对象函数的引用方式是——对象::函数名

静态函数的引用方式是——类名::函数名

我们将inflate拓展增加了一个高阶函数参数,这个高阶函数,就是XXXLayoutBinding.inflate方法。

使用也很简单:

val binding by inflate(PocketSquareLayoutBinding::inflate)

比前面使用反射的方式多了一个参数,但是好处是避免了反射。

文章出处在这里 zhuinden.medium.com/simple-one-…

再简单一点?

好像有点麻烦,但是好在Android Studio有代码模板功能,我们还可以尽量再简化一点。
打开AS的Live Templates,在Kotlin下增加一个模板,触发代码设置为「byVB」(当然你可以自定义):
private val binding by inflate( C L A S S CLASS CLASS::inflate)
这样我们在Kotlin代码中,直接输入byVB,代码就自动帮我们补全了,只用输入Binding类名即可。
ViewBinding的封装其实见仁见智,它的使用确实不如kotlin-android-extensions方便,但是天下大势所趋,也没有办法,随着Kotlin的升级,早晚还是要切换到ViewBinding。
向大家推荐下我的网站 xuyisheng.top/ 专注 Android-Kotlin-Flutter 欢迎大家访问

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
入研究,那么很难做到真正的技术提升。**

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Go)
[外链图片转存中…(img-DxhH4lyu-1713313139895)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值