13.Android之注解问题
目录介绍
- 13.0.0.1 什么是注解?系统内置的标准注解有哪些?SuppressWarnings用过没?Android中提供了哪些与线程相关的注解?
- 13.0.0.2 什么是apt?apt的难点和优势?什么是注解处理器?抽象处理器中四个方法有何作用?annotationProcessor和apt区别?
- 13.0.0.3 注解是怎么分类的?自定义注解又是怎么分类的?运行期注解原理是什么?实际注解案例有哪些?
- 13.0.0.4 在自定义注解中,Annotation里面的方法为何不能是private?Annotation里面的方法参数有哪些?
- 13.0.0.5 @Inherited是什么意思?注解是不可以继承的,这是为什么?注解的继承这个概念该如何理解?
- 13.0.0.6 什么是依赖注入?依赖注入案例举例说明,有哪些方式,具备什么优势?依赖查找和依赖注入有什么区别?
- 13.0.0.7 路由框架为何需要依赖注入,不用的话行不行?路由用什么方式注入,这些注入方式各具何特点,为何选择注解注入?
- 13.0.0.8 实际开发中使用到注解有哪些,使用注解替代枚举?如何通过注解限定传入的类型?为何说枚举损耗性能?
注解基础系列博客
- 01.Annotation注解详细介绍
1.Annotation库的简单介绍 2.@Nullable和@NonNull 3.资源类型注释 4.类型定义注释 5.线程注释 6.RGB颜色纸注释 7.值范围注释 8.权限注释 9.重写函数注释 10.返回值注释 11.@Keep注释 12.@SuppressWarnings注解 13.其他 复制代码
- 02.Dagger2深入分析,待更新
- 03.注解详细介绍
- 什么是注解,注解分类有哪些?自定义注解分类?运行注解案例展示分析,以一个最简单的案例理解注解……使用注解替代枚举,使用注解限定类型
- 04.APT技术详解
- 什么是apt?理解注解处理器的作用和用途……android-apt被替代?annotationProcessor和apt区别? 什么是jack编译方式?
- 06.自定义annotation注解
- @Retention的作用?@Target(ElementType.TYPE)的解释,@Inherited注解可以被继承吗?Annotation里面的方法为何不能是private?
- 07.注解之兼容kotlin
- 后期更新
- 08.注解之处理器类Processor
- 处理器类Processor介绍,重要方法,Element的作用,修饰方法的注解和ExecutableElement,了解修饰属性、类成员的注解和VariableElement……
- 10.注解遇到问题和解决方案
- 无法引入javax包下的类库,成功运行一次,修改代码后再运行就报错
- 11.注解代替枚举
- 在做内存优化时,推荐使用注解代替枚举,因为枚举占用的内存更高,如何说明枚举占用内存高呢?这是为什么呢?
- 12.注解练习案例开源代码
- 注解学习小案例,比较系统性学习注解并且应用实践。简单应用了运行期注解,通过注解实现了setContentView功能;简单应用了编译器注解,通过注解实现了防暴力点击的功能,同时支持设置时间间隔;使用注解替代枚举;使用注解一步步搭建简单路由案例。结合相应的博客,在来一些小案例,从此应该对注解有更加深入的理解……
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
- 链接地址:github.com/yangchong21…
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议或者问题,万事起于忽微,量变引起质变!
13.0.0.1 什么是注解?系统内置的标准注解有哪些?SuppressWarnings用过没?Android中提供了哪些与线程相关的注解?
- 什么是注解?
- Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息或者任何元数据(metadata)的途径和方法。基本规则:Annotation(注解)不能影响程序代码的执行,无论增加,删除Annotation(注解),代码都始终如一的执行。
- 系统内置的标准注解有哪些?
- @Override表示子类对父类方法的重写所带的注解;@Deprecated表示已经过时,不建议使用,但是依然可以使用;@SuppressWarnings("all")用来抑制编译时的警告信息,编译器在你写代码的时候,难免会出现很多的警告,有强迫症的程序猿会感到极其不爽,那么肿么办呢?@SuppressWarnings注解就可以告诉编译器,别警告啦,代码不会有问题的。
- SuppressWarnings用过没?
- @SuppressWarnings注解一定要传递一个参数给它,来表示过滤掉哪些类型的警告,笔者添加了”all”表示过滤掉所有类型的警告,很好理解吧!那么还可以传递什么参数来过滤警告呢?看看下面的表格你就会知道啦:
- Android中提供了哪些与线程相关的注解?
- @UiThread,通常可以等同于主线程,标注方法需要在UIThread执行,比如View类就使用这个注解
- @MainThread 主线程,经常启动后创建的第一个线程
- @WorkerThread 工作者线程,一般为一些后台的线程,比如AsyncTask里面的doInBackground就是这样的
- @BinderThread 注解方法必须要在BinderThread线程中执行,一般使用较少
13.0.0.2 什么是apt?apt的难点和优势?什么是注解处理器?抽象处理器中四个方法有何作用?annotationProcessor和apt区别?
- 什么是apt?
- APT(Annotation Processing Tool的简称),可以在代码编译期解析注解,并且生成新的Java文件,减少手动的代码输入。现在有很多主流库都用上了 APT,比如 Dagger2, ButterKnife等
- apt的难点和优势?
- 难点:就apt本身来说没有任何难点可言,难点一在于设计模式和解耦思想的灵活应用,二在与代码生成的繁琐,你可以手动字符串拼接,当然有更高级的玩法用squareup的javapoet,用建造者的模式构建出任何你想要的源代码
- 优点:它的强大之处无需多言,看代表框架的源码,你可以学到很多新姿势。总的一句话:它可以做任何你不想做的繁杂的工作,它可以帮你写任何你不想重复代码。
- 什么是注解处理器?
- 注解处理器是一个在javac中的,用来编译时扫描和处理的注解的工具。你可以为特定的注解,注册你自己的注解处理器。
- 注解处理器可以生成Java代码,这些生成的Java代码会组成 .java 文件,但不能修改已经存在的Java类(即不能向已有的类中添加方法)。而这些生成的Java文件,会同时与其他普通的手写Java源代码一起被javac编译。
- 抽象处理器中四个方法有何作用?
- 每一个注解处理器都要继承于AbstractProcessor,如下所示:
public class MyProcessor extends AbstractProcessor{@Overridepublic synchronized void init(ProcessingEnvironment processingEnvironment){super.init(processingEnvironment);}@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment){return false;}@Overridepublic Set<String> getSupportedAnnotationTypes(){return super.getSupportedAnnotationTypes();}@Overridepublic SourceVersion getSupportedSourceVersion(){return super.getSupportedSourceVersion();} } 复制代码
- 这几个方法如下
- init(ProcessingEnvironment processingEnvironment): 每一个注解处理器类都必须有一个空的构造函数。然而,这里有一个特殊的init()方法,它会被注解处理工具调用,并输入ProcessingEnviroment参数。ProcessingEnviroment提供很多有用的工具类Elements,Types和Filer。后面我们将看到详细的内容。
- process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment): 这相当于每个处理器的主函数main()。你在这里写你的扫描、评估和处理注解的代码,以及生成Java文件。输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素。后面我们将看到详细的内容。
- getSupportedAnnotationTypes(): 这里你必须指定,这个注解处理器是注册给哪个注解的。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。换句话说,你在这里定义你的注解处理器注册到哪些注解上。
- getSupportedSourceVersion(): 用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。然而,如果你有足够的理由只支持Java 7的话,你也可以返回SourceVersion.RELEASE_7。我推荐你使用前者。
- 每一个注解处理器都要继承于AbstractProcessor,如下所示:
- annotationProcessor和apt区别?
- Android 官方的 annotationProcessor 同时支持 javac 和 jack 编译方式,而 android-apt 只支持 javac 方式。当然,目前 android-apt 在 Android Gradle 插件 2.2 版本上面仍然可以正常运行,如果你没有想支持 jack 编译方式的话,可以继续使用 android-apt。
- 什么是jack编译方式?
- Jack (Java Android Compiler Kit)是新的Android 编译工具,从Android 6.0 开始加入,替换原有的编译工具,例如javac, ProGuard, jarjar和 dx。它主要负责将java代码编译成dex包,并支持代码压缩,混淆等。
- Jack工具的主要优势
- 完全开放源码,源码均在AOSP中,合作伙伴可贡献源码
- 加快编译源码,Jack 提供特殊的配置,减少编译时间:pre-dexing, 增量编译和Jack编译服务器.
- 支持代码压缩,混淆,重打包和multidex,不在使用额外单独的包,例如ProGuard。
13.0.0.3 注解是怎么分类的?自定义注解又是怎么分类的?运行期注解原理是什么?
- 注解是怎么分类的?
- 标准 Annotation
- 包括 Override, Deprecated, SuppressWarnings,是java自带的几个注解,他们由编译器来识别,不会进行编译, 不影响代码运行,至于他们的含义不是这篇博客的重点,这里不再讲述。
- 元 Annotation
- @Retention, @Target, @Inherited, @Documented,它们是用来定义 Annotation 的 Annotation。也就是当我们要自定义注解时,需要使用它们。
- 自定义 Annotation
- 根据需要,自定义的Annotation。而自定义的方式,下面我们会讲到。
- 标准 Annotation
- 自定义注解又是怎么分类的?
- 同样,自定义的注解也分为三类,通过元Annotation - @Retention 定义:
- @Retention(RetentionPolicy.SOURCE)
- 源码时注解,一般用来作为编译器标记。如Override, Deprecated, SuppressWarnings。
- @Retention(RetentionPolicy.RUNTIME)
- 运行时注解,在运行时通过反射去识别的注解。
- 定义运行时注解,只需要在声明注解时指定@Retention(RetentionPolicy.RUNTIME)即可。
- 运行时注解一般和反射机制配合使用,相比编译时注解性能比较低,但灵活性好,实现起来比较简答。
- @Retention(RetentionPolicy.CLASS)
- 编译时注解,在编译时被识别并处理的注解,这是本章重点。
- 编译时注解能够自动处理Java源文件并生成更多的源码、配置文件、脚本或其他可能想要生成的东西。
- 运行期注解原理是什么?
- 实际注解案例有哪些?
- 运行时注解:retrofit
- 编译时注解:Dagger2, ButterKnife, EventBus3
13.0.0.4 在自定义注解中,Annotation里面的方法为何不能是private?Annotation里面的方法参数有哪些?
- Annotation里面的方法为何不能是private?
- 只能用public或默认(default)这两个访问权修饰.例如,String value();不能是private;因为它是提供给外部使用的。
- Annotation里面的方法参数有哪些
- 参数只能使用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数类型就为String;
13.0.0.5 @Inherited是什么意思?注解是不可以继承的,这是为什么?注解的继承这个概念该如何理解?
- @Inherited是什么意思?
- 该注解的字面意识是继承,但你要知道注解是不可以继承的。@Inherited是在继承结构中使用的注解。
- 如果你的注解是这样定义的:
- 当你的注解定义到类A上,此时,有个B类继承A,且没使用该注解。但是扫描的时候,会把A类设置的注解,扫描到B类上。
@Inherited @Retention(RetentionPolicy.CLASS) @Target(ElementType.TYPE) public @interface Test {//... } 复制代码
- 注解是不可以继承的,这是为什么?
- 注解不能继承
- 注解的继承这个概念该如何理解?
- 这里讲的继承并不是通过@Inherited修饰的注解。这个“继承”是一个注解的使用技巧,使用上的感觉类似于依赖倒置,来自于ButterKnife源码。
- 这是ButterKnife的OnClick 注解。特殊的地方在于**@OnClick修饰了注解@ListenerClass**,并且设置了一些只属于@OnClick的属性。
- 那这样的作用是什么呢?凡是修饰了@OnClick的地方,也就自动修饰了@ListenerClass。类似于@OnClick是@ListenerClass的子类。而ButterKnife有很多的监听注解@OnItemClick、@OnLongClick等等。这样在做代码生成时,不需要再单独考虑每一个监听注解,只需要处理@ListenerClass就OK。
@Target(METHOD) @Retention(CLASS) @ListenerClass(targetType = "android.view.View",setter = "setOnClickListener",type = "butterknife.internal.DebouncingOnClickListener",method = @ListenerMethod(name = "doClick",parameters = "android.view.View") ) public @interface OnClick {/** View IDs to which the method will be bound. */int[] value() default { View.NO_ID }; } 复制代码
13.0.0.6 什么是依赖注入?依赖注入案例举例说明,有哪些方式,具备什么优势?依赖查找和依赖注入有什么区别?
- 什么是依赖注入
- 在面向对象编程中,经常处理处理的问题就是解耦,程序的耦合性越低表明这个程序的可读性以及可维护性越高。控制反转(Inversion of Control或IoC)就是常用的面向对象编程的设计原则,使用这个原则我们可以降低耦合性。其中依赖注入是控制反转最常用的实现。
- 依赖注入案例举例说明,有哪些方式,具备什么优势?
- 依赖是程序中常见的现象,比如类Car中用到了GasEnergy类的实例energy,通常的做法就是在Car类中显式地创建GasEnergy类的实例,并赋值给energy。如下面的代码
interface Energy {}class GasEnergy implements Energy {}class Car {Energy energy = new GasEnergy(); } 复制代码
- 存在问题
- 类Car承担了多余的责任,负责energy对象的创建,这必然存在了严重的耦合性。举一个现实中的例子,一辆汽车使用哪种能源不是由汽车来决定,而是由汽车制造商(CarMaker)来决定,这是汽车制造商的责任。
- 可扩展性,假设我们想修改能源为电动力,那么我们必然要修改Car这个类,明显不符合开放闭合原则。
- 不利于单元测试。
- 有哪些方式解耦
- 依赖注入是这样的一种行为,在类Car中不主动创建GasEnergy的对象,而是通过外部传入GasEnergy对象形式来设置依赖。 常用的依赖注入有如下三种方式
- 构造器注入
- 将需要的依赖作为构造方法的参数传递完成依赖注入。
class Car {Energy mEnergy;public Car(Energy energy) {mEnergy = energy;} } 复制代码
- Setter方法注入
- 增加setter方法,参数为需要注入的依赖亦可完成依赖注入。
class Car {Energy mEnergy;public void setEnergy(Energy energy) {mEnergy = energy;} } 复制代码
- 接口注入
- 接口注入,闻其名不言而喻,就是为依赖注入创建一套接口,依赖作为参数传入,通过调用统一的接口完成对具体实现的依赖注入。
- 接口注入和setter方法注入类似,不同的是接口注入使用了统一的方法来完成注入,而setter方法注入的方法名称相对比较随意。
interface EnergyConsumerInterface {public void setEnergy(Energy energy); }class Car implements EnergyConsumerInterface {Energy mEnergy;public void setEnergy(Energy energy) {mEnergy = energy;} } 复制代码
- 依赖是程序中常见的现象,比如类Car中用到了GasEnergy类的实例energy,通常的做法就是在Car类中显式地创建GasEnergy类的实例,并赋值给energy。如下面的代码
- 依赖查找和依赖注入
- 依赖查找和依赖注入一样属于控制反转原则的具体实现,不同于依赖注入的被动接受,依赖查找这是主动请求,在需要的时候通过调用框架提供的方法来获取对象,获取时需要提供相关的配置文件路径、key等信息来确定获取对象的状态。
13.0.0.7 路由框架为何需要依赖注入,不用的话行不行?路由用什么方式注入,这些注入方式各具何特点,为何选择注解注入?
- 路由框架为何需要依赖注入,不用的话行不行?
- 路由的目的就是要实现跳转,但是你有没有想过,两个Activity之间的跳转肯定免不了要传入一些参数,如果我们在跳转后还要通过intent去获取参数,这样岂不是很麻烦,如果可以自动把参数赋给属性多好啊!
- 组件化中两个module之间可能有一些功能并不需要跳转页面,如支付模块要获取用户模块的用户id,并不需要跳转页面,那么我们就要持有用户模块含有获取用户id功能的类的引用,如果我们在支付模块创建一个用户模块的功能引用,显然就违背了解耦的规则。这两个问题显然用依赖注入的方式会更好些,如果你用过ARouter,你会发现ARouter中的服务(IProvider)就是通过依赖注入实现的。
- 路由用什么方式注入,这些注入方式各具何特点,为何选择注解注入?
- 可以使用注解的方式,至于为啥,接下来我分析一下……
- 为什么要用注解实现依赖注入,因为我们用了apt啊,那岂不是天生实现依赖注入的利器。如果你去写配置文件或构造方法等等,未免太复杂。
- 无法通过构造方法注入【构造器注入】
- 在多组件并行开发过程中,因为两个module没有引用关系,所以就不能通过构造方法传入要依赖的类,这个时候怎么办呢?连对方的引用都得不到,如何进行依赖呢?
- 不要通过反射方式注入
- 可能你会想到反射,我们先pass这个方案,能不用反射就能做好的前提下,我们最好不要用反射。
- 不建议通过接口方式注入【也可以,但若是开源成lib,则不建议】
- 可能有人会想到,在基类下沉一个接口功能标准,比如在基类库base模块定义获取用户id的接口,然后在用户模块实现接口的方法。那么当支付模块需要用到这个功能,就声明这个接口,然后一行注解通过框架为你创建实例,这样用户模块只需要提供功能,并不需要关心谁在用这个功能,这样岂不是大大减小了耦合。
- 但是有一点,组件化实践中,有很多个模块,那岂不是所有的都需要依赖base基类库,才能使用到接口注入,这样不易转接。
- 可以使用注解的方式,至于为啥,接下来我分析一下……
13.0.0.8 实际开发中使用到注解有哪些,使用注解替代枚举?如何通过注解限定传入的类型?为何说枚举损耗性能?
- 实际开发中使用到注解有哪些,使用注解替代枚举?
- 代码如下所示
- 具体的案例,可以看我视频播放器开源库:github.com/yangchong21…
/*** 播放模式* -1 播放错误* 0 播放未开始* 1 播放准备中* 2 播放准备就绪* 3 正在播放* 4 暂停播放* 5 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放)* 6 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停* 7 播放完成*/ public @interface CurrentState{int STATE_ERROR = -1;int STATE_IDLE = 0;int STATE_PREPARING = 1;int STATE_PREPARED = 2;int STATE_PLAYING = 3;int STATE_PAUSED = 4;int STATE_BUFFERING_PLAYING = 5;int STATE_BUFFERING_PAUSED = 6;int STATE_COMPLETED = 7; } 复制代码
- 如何通过注解限定传入的类型?
- 代码如下所示
- 具体的案例,可以看我视频播放器开源库:github.com/yangchong21…
- 枚举最大的作用是提供了类型安全。为了弥补Android平台不建议使用枚举的缺陷,官方推出了两个注解,IntDef和StringDef,用来提供编译期的类型检查。
- 倘若,传入的值不是IjkPlayerType中的类型,则会导致编译提醒和警告。
/*** 通过注解限定类型* TYPE_IJK IjkPlayer,基于IjkPlayer封装播放器* TYPE_NATIVE MediaPlayer,基于原生自带的播放器控件*/ @Retention(RetentionPolicy.SOURCE) public @interface IjkPlayerType {int TYPE_IJK = 111;int TYPE_NATIVE = 222; } @IntDef({IjkPlayerType.TYPE_IJK,IjkPlayerType.TYPE_NATIVE}) public @interface PlayerType{}//使用 /*** 设置播放器类型,必须设置* 注意:感谢某人建议,这里限定了传入值类型* 输入值:ConstantKeys.IjkPlayerType.TYPE_IJK 或者 ConstantKeys.IjkPlayerType.TYPE_NATIVE* @param playerType IjkPlayer or MediaPlayer.*/ public void setPlayerType(@ConstantKeys.PlayerType int playerType) {mPlayerType = playerType; } 复制代码
关于其他内容介绍
01.关于博客汇总链接
- 1.技术博客汇总
- 2.开源项目汇总
- 3.生活博客汇总
- 4.喜马拉雅音频汇总
- 5.其他汇总
02.关于我的博客
- 我的个人站点:www.yczbj.org,www.ycbjie.cn
- github:github.com/yangchong21…
- 知乎:www.zhihu.com/people/yczb…
- 简书:www.jianshu.com/u/b7b2c6ed9…
- csdn:my.csdn.net/m0_37700275
- 喜马拉雅听书:www.ximalaya.com/zhubo/71989…
- 开源中国:my.oschina.net/zbj1618/blo…
- 泡在网上的日子:www.jcodecraeer.com/member/cont…
- 邮箱:yangchong211@163.com
- 阿里云博客:yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
- segmentfault头条:segmentfault.com/u/xiangjian…
- 掘金:juejin.im/user/593943…
03.12.注解练习案例开源代码
13.Android之注解问题相关推荐
- android注解的作用,Android 用注解来提升代码质量
Android 用注解来提升代码质量 Android,注解,annotation 2018.07.13 Android 提供了一个注解的 support 包,这个注解包配合 IDE 可以用来提升我的代 ...
- 细说 Android Annotations 注解框架
本文首发知识星球<Hi Android> 注解不是必须的,但是能极大的帮助我们节约时间和提高开发效率,写此篇文章的初衷,是我课程中的同学想要了解一下这个框架,遂写下此篇文章,其实我们如果想 ...
- 《Android App开发入门:使用Android Studio 2.X开发环境》——1-3 Android Studio 快速上手...
1-3 Android Studio 快速上手
- Android Annotation注解详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119874435 本文出自[赵彦军的博客] 文章目录 Java注解 元注解说明 @R ...
- android 使用注解
使用注解改进代码检查 本文内容 向您的项目添加注解 添加支持注解库依赖项 运行代码检查 Nullness 注解 Nullability 分析 资源注解 线程注解 值约束注解 权限注解 间接权限 返回值 ...
- 【SA8295P 源码分析】13 - Android GVM 虚拟机 QUPv3 UART / SPI / I2C功能配置及透传配置
[SA8295P 源码分析]13 - Android GVM 虚拟机 QUPv3 UART / SPI / I2C功能配置及透传配置 一.QUP v3 介绍 二.QUP v3 UART 功能配置 2. ...
- Android 自定义注解(Annotation)
现在市面上很多框架都有使用到注解,比如butterknife库.EventBus库.Retrofit库等等.也是一直好奇他们都是怎么做到的,注解的工作原理是啥.咱们能不能自己去实现一个简单的注解呢.注 ...
- Android 基于注解IOC组件化/模块化的架构实践
当前参与的项目历史也很久远,第一行代码据说是写于2014年的某一天,那时Android用的ide还是Eclipse.那时Android还没有很好的架构指导(mvp.mvvm).那时Android最新的 ...
- android使用 注解框架,Android实践 | 注解框架ButterKnife基本使用
使用ButterKnife,我们可以不用写很多的findViewById()语句,以及通过getResources获取String.Color等资源,这可以让我们的代码更加简洁,使用起来也很方便.下面 ...
最新文章
- xgboost 的 get_fscore()
- Quartz调度器学习--基本概念
- 常用的Linux命令合集,建议收藏保存!
- (一)ubuntu下qtcreator +opencv下新建一个项目和调用caffe环境配置
- 云计算学习(1-1)云计算的定义
- Bitmovin:视频开发者报告2018
- C语言高级编程:数组和指针作为函数形参
- 微软:Vista SP2是最安全的操作系统
- [react] React Intl是什么原理?
- python 加权随机算法_python中的加权随机样本
- java代码实际_Java 8会给你的代码带来什么:一个实际的例子
- redis用zset做延时消息
- 【渝粤教育】广东开放大学 经济学基础 形成性考核 (25)
- VM虚拟机下CentOS 6.5配置IP地址的三种方法
- (专升本)Excel(分页符的删除)
- 【iOS】 Foundation 数组
- 微软认知服务应用秘籍 – 支持跨平台客户端的视觉服务中间层
- java redis 实现pv uv_redis实战-记录PV与UV
- 2022年全球与中国湿钽电容器行业发展趋势及投资战略分析报告
- Google MicroData,谷歌微数据为博客添加评级
热门文章
- 计算机控制的电冰箱,详解电脑控制型电冰箱维修基础
- 快速理解j=j++ 和 j=++j(新手入门)
- Web功能设计:验证码
- 16S的细菌群落功能预测工具PICRUSt2学习
- 海思芯片怎么使用tde给qt加速_海思芯片图形层的开发指南与方案
- jupyter notebook中使用R语言
- android数据回传多个页面_Android菜鸟起飞|使用Intent实现Activity跳转的两种方式(无回传数据和有回传数据)...
- EDIUS压片模糊问题该怎样解决
- DDPush开源推送框架源码分析之APPServer到DDPush
- 8月28日服务器例行维护公告,2008年8月28日维护公告