自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数HarmonyOS鸿蒙开发工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年HarmonyOS鸿蒙开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上HarmonyOS鸿蒙开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新
如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注鸿蒙获取)
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
为了解决上述类型擦除问题,以及更好的使用体验。Kotlin
中存在名为 reified
的关键字,它可以被作用于函数上, 以此做到类型擦除后的再生,便于开发者优雅的使用泛型以及获取方法的泛型类型。
在 Java
中,如果我们要获取函数的泛型类型,一般会通过给函数中传递类型参数的方式,如下所示:
public <T extends Activity> void startActivity(Context context, Class<T> c) {
context.startActivity(new Intent(context, c));
}
如果上述代码使用 kotlin
来写呢?如下所示:
inline fun <reified C : Activity> Context.startActivityKtx() {
startActivity(Intent(this, C::class.java))
}
我们利用 扩展函数 +
reified
关键字的方式,减少了模版代码,增强了使用体验。从而让本该在编译阶段被擦除的Activity类型,能够在运行时获取到。
但需要注意的是,reified
关键字必须和 inline
关键字一起使用(下面会提到为什么)。
inline 关键字是什么呢?
简单理解为:当一个函数被标记为
inline
时,kotlin编译器 会在所有调用这个函数的位置,将方法函数替换为具体的函数体。
解析
通过查看 kotlin 字节码,我们可以得知 reified
的底层实现。
例如下面示例与其对应的字节码:
inline fun <reified C : Activity> Context.toAct() {
startActivity(Intent(this, C::class.java))
}
fun test(context: Context) {
context.toAct<MainActivity>()
}
// $FF: synthetic method
public static final void toAct(Context $this$toAct) {
int $i$f$toAct = 0;
Intrinsics.checkNotNullParameter($this$toAct, "$this$toAct");
Intrinsics.reifiedOperationMarker(4, "C");
$this$toAct.startActivity(new Intent($this$toAct, Activity.class));
}
public static final void test(@NotNull Context context) {
Intrinsics.checkNotNullParameter(context, "context");
int $i$f$toAct = false;
context.startActivity(new Intent(context, MainActivity.class));
}
我们在 test() 方法中调用toAct(),不难发现,toAct()的逻辑已经被移动到了 test() 中,而我们的泛型类型也被替换为实际使用的类型,从而我们可以在方法函数中直接获取相应的泛型类型。
这也就是为什么 reified
必须要增加 inline
,因为其必须内联才能知道具体类型,从而将我们的实际泛型类型更新到具体的调用代码中,从而完成泛型类型 再生 。
小提示
Java中无法调用
需要注意的是,reified
无法在java中进行调用,为什么呢?
因为 Java
并没有内联的特性,我们使用的 inline
方法在 Java
中会被当做普通方法,而 reified
正是需要内联才可以保证泛型再生,所以自然无法调用。
从源码上来说,对于reified 关键字的方法,相应的字节码生成时会增加 // $FF: synthetic method
的标记。
如下示例所示:
inline fun <reified C : Activity> Context.toAct() {
...
}
// $FF: synthetic method
public static final void toAct(Context $this$toAct) {
...
}
// $FF: synthetic method
如果你经常写组件,肯定见过这段注释。你可以理解这只是一个标记,其作用为告诉编译器 禁止java代码在编译期访问该方法 。
比如我们在写 kotlin 组件,而且要同时满足 java 调用时,经常会免不了使用 internal
,即 模块可见 。但相应的,该关键字修饰的方法或者字段在Java中却依然可以被调用,甚是让java调用者费解与不优雅。所以相应的,对于方法,我们可以增加 @JvmSynthetic
,从而避免java代码编译期调用。而 reified
也是正是采用了该思路。
用时,经常会免不了使用 internal
,即 模块可见 。但相应的,该关键字修饰的方法或者字段在Java中却依然可以被调用,甚是让java调用者费解与不优雅。所以相应的,对于方法,我们可以增加 @JvmSynthetic
,从而避免java代码编译期调用。而 reified
也是正是采用了该思路。