详解Android主流框架不可或缺的基石

自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onLayout源码详尽分析 自定义View系列教程04–Draw源码分析及其实践 自定义View系列教程05–示例分析 自定义View系列教程06–详解View的Touch事件处理 自定义View系列教程07–详解ViewGroup分发Touch事件 自定义View系列教程08–滑动冲突的产生及其处理

前言

经过几年的发展和沉淀,Android开发中涌现出许多优秀的框架,比如:Retrofit、Afinal、OKHttp、ButterKnife、AndFix等等。这些框架的出现极大地简化了开发流程,提高了工作效率。在项目开发的过程中我们主要是使用这些轮子完成项目,很难有时间去顾及框架的内部实现。在项目交付之后我们可能就要去看看这些框架的源码了。

这些主流框架的功能各不相同,但每当打开浩繁的源码时我们几乎都可以看到反射,注解,泛型的广泛应用;也正是这些技术使得框架具有了高度的灵活性,优良的扩展性和健壮的稳定性。鉴于这些框架必备知识的重要性故在此对这部分内容做一个全面的梳理和总结。

主要内容:

ClassLoader

ClassLoader的分析

几种不同ClassLoader的介绍

ClassLoader的应用

泛型

泛型的由来

自定义泛型

泛型的擦除

反射

Class

常用反射技术

Type以及ParameterizedType

反射与泛型的结合使用

注解

常用注解的介绍和使用

元注解

自定义注解及其使用

ClassLoader

在程序运行时首先要将类加载到内存中,这个加载工作就是由ClassLoader完成的,故在中文文档中将其翻译为”类加载器”。 那么我们代码中所用到的类有什么不同呢?——它们的”来源”是不一样的。 有的类是属于系统提供的类,比如:String、Date、Object等 所以,在Android系统启动时会自动创建一个Boot类型的ClassLoader,该ClassLoader用于加载一些系统层级的类。 有的类属于我们自己写的类,比如:User、Girl、Beauty等等 所以,每个APP会创建一个自己的ClassLoader实例,该ClassLoader用于加载dex。 嗯哼,我们再通过代码来验证一下:

/*** 原创作者:* 谷哥的小弟** 博客地址:* */private void getClassLoaders() {ClassLoader classLoader = getClassLoader();while (null != classLoader) {System.out.println(“—-> classLoader=” + classLoader);classLoader = classLoader.getParent();}}

输出结果如下所示:

此处一共展示了两个ClassLoader

第一个ClassLoader,如下:

dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/cc.testreflection-2/base.apk”],nativeLibraryDirectories=[/vendor/lib,/system/lib]]]

该PathClassLoader在应用启动时创建,用于加载/data/app/cc.testreflection-2/base.apk中的类。

ClassLoader是一个抽象类,它有三个常用的子类:PathClassLoader、URLClassLoader、DexClassLoader。

PathClassLoader 它只能加载已经安装的apk中的资源,比如dex文件 URLClassLoader 它只能用于加载jar文件中的资源。但是dalvik不能直接识别jar,所以这个加载器极少使用。 DexClassLoader 它用于从.jar和.apk类型的文件内部加载classes.dex。该类加载器常用来完成动态加载apk的需求。

第二个ClassLoader,如下:

classLoader=java.lang.BootClassLoader@21b737fd

该BootClassLoader在系统启动的时候创建,用于加载系统层级的类。

在认识了这两种类加载器之后,我们看看它们的应用。

/*** 原创作者:* 谷哥的小弟** 博客地址:* */private void testClassLoader() {try {Class clazz = Class.forName(“cc.testreflection.Girl”);ClassLoader classLoader = clazz.getClassLoader();System.out.println(“—-> classLoader=” + classLoader);classLoader = mContext.getClass().getClassLoader();InputStream inputStream = classLoader.getResourceAsStream(“assets/ic_launcher.png”);System.out.println(“—-> classLoader=” + classLoader);clazz = Class.forName(“java.lang.String”);classLoader = clazz.getClassLoader();System.out.println(“—-> classLoader=” + classLoader);} catch (Exception e) {}}

输出结果如下所示:

嗯哼,和之前的分析一样: 我们自己的类cc.testreflection.Girl和assets文件夹中的图片ic_launcher.png都是由PathClassLoader加载的,而java.lang.String是由BootClassLoader加载的。

泛型

泛型始现于JDK1.5,从那以后大家在项目常常使用泛型,比如:

ArrayList<Girl> arrayList=new ArrayList<Girl>();for(int i=0;i<10;i++){Girl girl =new Girl();arrayList.add(girl);}

在与此类似的场景中利用泛型限定了集合中的输入类型,从而让编译器屏蔽了源程序中的非法数据输入,比如此时往ArrayList<Girl>中add一个Boy就无法通过编译器的编译。

刚才已经说了,泛型主要是给编译器看的;那么在编译完成之后生成的字节码里泛型会发生什么变化呢?来看个例子:

private void testArraylistClass() {Class clazz1 = new ArrayList<Integer>().getClass();Class clazz2 = new ArrayList<String>().getClass();boolean isEqual=(clazz1 == clazz2);System.out.println(“—-> isEqual=” +isEqual);}

输出结果:

—-> isEqual=true

不要害怕错过什么,因为在路上你就已经收获了自由自在的好心情。

详解Android主流框架不可或缺的基石

相关文章:

你感兴趣的文章:

标签云: