2024年最全Kotlin开发效率提升技巧—扩展函数,最新BAT大厂面试者整理的Android面试题目

总结

我最近从朋友那里收集到了2020-2021BAT 面试真题解析,内容很多也很系统,包含了很多内容:Android 基础、Java 基础、Android 源码相关分析、常见的一些原理性问题等等,可以很好地帮助大家深刻理解Android相关知识点的原理以及面试相关知识

这份资料把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节;还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

这里也分享给广大面试同胞们,希望每位程序猿们都能面试成功~

Android 基础知识点

Java 基础知识点

Android 源码相关分析

常见的一些原理性问题

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2020面试真题解析

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

之后,在需要dp转px的地方调用如下方法就可以了。

float pxValue = Util.dp2px(20f, context)

这也是在Java中最常规的操作了,现在使用Kotlin之后,同样也可以定义一个一模一样的工具类进行数值转换,但是Kotlin中有更加优雅的写法。

新建一个Extensions.kt文件,编写如下代码:

fun Float.dp2px(context: Context) : Float {

return TypedValue.applyDimension(

TypedValue.COMPLEX_UNIT_DIP,

this,

context.resources.displayMetrics

)

}

然后,使用下面的写法就可以进行dp转px了

val pxValue = 20f.dp2px(context)

Kotlin扩展函数的基本结构如下:

fun ClassName.methodName(param: ParamType) : ReturnType {

// 具体实现

}

  • ClassName就是实际调用该方法的具体类的类型

  • methodName是方法的名称

  • param是方法传入的参数,可以为空,也可以有多个

  • ReturnType是方法的返回值类型,可以是任意类型

相比于定义一个普通的函数,定义扩展函数只需要在函数名的前面加上一个ClassName. 的语法结构,就表示将该函数添加到指定类当中了。

另外,扩展函数是一个顶层函数,可以将它写在任意一个类中,一般就以ClassName名称新建一个文件,编写跟这个类相关的扩展函数,或者建一个统一管理扩展函数的文件,比如Extensions.kt。

扩展函数的本质

上面的kotlin扩展函数的这种写法给人感觉就是Float这个类中有一个dp2px方法,那么Kotlin是如何实现的这个神奇功能呢,我们看看这个Extensions.kt文件的kotlin字节码反编译成Java语言后都干了些啥。

具体查看步骤:Android Studio的Tools菜单栏 -> Kotlin -> Show Kotlin Bytecode -> 然后Kotlin Bytecode面板上点击Decompile按钮就可以如下代码(已简化):

public final class ExtensionsKt {

public static final float dp2px(float t h i s this thisdp2px, @NotNull Context context) {

Resources var10002 = context.getResources();

return TypedValue.applyDimension(1, t h i s this thisdp2px, var10002.getDisplayMetrics());

}

}

可以看到反编译之后的Java代码,其实就是在ExtensionsKt类中定义了一个static final方法,上面写的20f.dp2px(context) 就是调用的这个方法,而Float类中并不存在dp2px方法,我们也不可能去修改Float类。我们发现反编译的java函数比我们定义的扩展函数,多了一个float参数,这个参数的类型正是定义扩展函数时的ClassName类型,调用时相当于把20f作为参数传入了静态方法,这样做,一是限定了调用该扩展函数的调用者类型,二是为扩展函数内部计算提供了该对象数据。

对于扩展函数还需要注意以下两点。

一、扩展函数是静态解析的,是采用静态分派的过程来处理

这是说调用的扩展函数是由函数调用所在的表达式的类型(定义时的ClassName)来决定的, 而不是由表达式运行时求值结果决定的。如果类本身和其子类都进行了同一个函数的扩展,这函数是不会有重写关系的,在使用的时候,只会根据需要使用该方法的对象的实际类型来决定是调用了哪个扩展函数。

比如下面的代码:

open class Shape

class Rectangle: Shape()

fun Shape.getName() = “Shape”

fun Rectangle.getName() = “Rectangle”

fun printClassName(s: Shape) {

println(s.getName())

}

printClassName(Rectangle())

结果会打印“Shape”,相当于是调用了Shape类中的静态方法,子类并不会影响父类。

二、如果一个类中定义了一个和成员函数一模一样的扩展函数,那么调用的时候始终会调用成员函数。

就是说一个类中定义了一个函数,然后又定义了一个和这个成员函数一样结构的扩展函数,调用的时候将不会调用到扩展函数,举个例子

class Example {

fun printFunctionType() { println(“Class method”) }

}

fun Example.printFunctionType() { println(“Extension function”) }

// 调用方法

Example().printFunctionType()

这段代码执行结果会打印"Class method"

更优雅的写法

对于上面dp转px的方法,其实还可以进一步优化,可以定义一个顶层属性。

val Float.dp

get() = TypedValue.applyDimension(

TypedValue.COMPLEX_UNIT_DIP,

this,

Resources.getSystem().displayMetrics

)

定义了一个dp属性,然后将dp转px的结果赋值给它的get方法,最后调用的时候只需要像下面这种方式写就可以了。

val pxValue = 20f.dp

这种写法是不是非常简洁!

这里有个小技巧,我们将传入参数Context来获取Resources的方式改为了Resources.getSystem() 的方式,这样就不用每次调用时传入一个context对象了,通过Resources.getSystem()获取的Resources不能用来获取App应用相关的东西,比如包名,但是获取手机系统相关的数据还是可以的,因为这里只需要用到displayMetrics,所以用这种方式获取Resources完全没问题。

其实这种顶层属性的写法同样也是会生成一个静态方法,看下反编译之后的Java代码就明白了。

public final class ExtensionsKt {

最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿

录播视频图.png

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

和视频教学资料,还有更多面试题等你来拿**

[外链图片转存中…(img-UofJy8pH-1715888662050)]

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

需要这份系统化学习资料的朋友,可以戳这里获取

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

  • 11
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值