android学习语法用法知识点

来源:互联网 发布:java ocx 编辑:程序博客网 时间:2024/04/28 01:48
1.引言
从JDK1.5开始,引入了注解类Annotation,Annotation其实是一种接口,可以作用于类、方法、属性等等 ,它可以通过反射机制来访问annotation信息,获取所加上注解信息,做相应的操作。相当于给相关的作用对象打上“tag”,使用方便,作用广泛。
2.java.lang中的注解
     在java.lang中,用到三种注解类,即常用到的Deprecated,Override和SuppressWarnings.
     2.1 @Deprecated 过时
     在使用Eclipse或AS编写程序过程中,有一些方法编写出来之后被画上了中划线,表示该方法已过时,建议使用新的一些方法代替。
     如:viewPager.setOnPageChangeListener()方法在安卓API23中已过时,在源代码中的该方法上赫然多了一个注解@Deprecated,可使用addOnPageChangeListener()方法代替。
     如果使用javac命令编译,会弹出:”注意:使用或覆盖了已过时的API“
     2.2 @Override 复写
     这是开发过程中最常遇到的注解了,表示复写父类中的方法。如果方法上有这条注解但没有重写父类方法,则会生成一条错误消息。这个注解有效地保证了方法一定会被复写。比如开发过程中,手动在子类中复写父类方法,只正确写出了方法名称,未写正确方法的参数,则相当于方法的重载,并不是复写。这种问题如果在功能上有错误产生,在检查过程中是很难找到的。使用@Override注解,有效地表明,此方法是复写父类的方法,不会产生手动的错误问题。
     2.3 @SuppressWarnings 阻止警告
     阻止了弹出的警告,比如屏蔽对上述过时的提示,可在调用setOnPageChangeListener()方法之上加上@SuppressWarnings("deprecation"),这样虽然在IDE中仍以中划线的形式表示,但如果使用javac命令就不再提示警告。
3.元注解
     那么以上的注解类的源码又是什么样的呢,打开Override发现其代码如下:
[java] view plain copy

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.SOURCE)  
    public @interface Override {  
    }  


这里可以发现注解类的定义方法以及注解类上所加的注解——元注解。元注解有四个,位于java.lang.annotation包中:Documented,Inherited,Retention,Target
     3.1@Target
     表示注解作用的目标。
[java] view plain copy

    @Documented  
    @Retention(RetentionPolicy.RUNTIME)  
    @Target(ElementType.ANNOTATION_TYPE)  
    public @interface Target {  
        ElementType[] value();  
    }  


注解可以作用的目标由枚举类ElementType决定,可作用于类、方法、属性等,数组表示注解可以有多个作用域。
[java] view plain copy

    public enum ElementType {  
        TYPE,// 类、接口、注解类型或枚举  
         FIELD, //属性  
         METHOD, //方法  
         PARAMETER,// 用于描述参数  
         CONSTRUCTOR,//构造方法  
          LOCAL_VARIABLE,//局部变量  
         ANNOTATION_TYPE,//注解类  
         PACKAGE //包  
    }  


注解作用于类时,定义@Target(ElementType.TYPE),ElementType .TYPE表示类型,Class,Interface等都实现了java中的Type接口,因此ElementType.TYPE 表示注解作用于这些"类"(并不是单纯的Class类)

     3.2@Retention
     表示注解的作用时段
[java] view plain copy

    @Documented  
    @Retention(RetentionPolicy.RUNTIME)  
    @Target(ElementType.ANNOTATION_TYPE)  
    public @interface Retention {  
        RetentionPolicy value();  
    }  


由此可见,Retention定义的是RetentionPolicy类型的数据,RetentionPolicy是一个枚举类型,包括SOURCE,CLASS,RUNTIME三个类型。表示注解保留的阶段。
SOURCE:表示注解只在源文件中保留
CLASS:表示注解保留到.class文件中
RUNTIME:表示注解一直保留到内存中,类加载器把.class文件加载到内存中产生的字节码中要保留注解信息。
可想而知,@Override仅在写代码时用到,其Retention中的值为RetentionPolicy.SOURCE,@SuppressWarnings也只是编译器使用的,保留到SOURCE阶段。而@Deprecated在内存中也需要保留,编译器需要得知方法是否过时,从加载到内存中的二进制文件中获取,因而要保留到RUNTIME阶段

     3.3@Documented
     注解只是一个标记的话,那么使用javadoc生成文档时,这些注解都不会存在于文档中,要使注解在文档中也存在,就可以在使用了注解的作用对象上加上@Documented这个注解。javadoc所生成的文档就会带上注解信息。

     3.4@Inherited
     该注解表示子类可以集成加载父类上的注解。但要注意:
     1.注解定义在类上面,子类是可以继承该注解
     2.注解定义在方法上面,子类也可以继承该注解,但是如果子类复写了父类中定义了注解的方法,那么子类将无法继承该方法的注解,也就是说,子类在复写父类中被@Inherited标注的方法时,会将该方法上面的注解覆盖掉
     3.Interface的实现类(implements实现)无法继承接口中所定义的被@Inherited标注的注解
4.注解的参数
在注解后为注解增加参数,如上述的@Retention、@Target后的括号中就是注解的参数。
参数的类型,支持基本数据类型、String类型、Class类型、enum类型、Annotation类型以及上述所有类型的数组。
当注解只有一个参数时,可以用value作为参数名称,在使用参数时,只用在括号中写参数的值而不用写参数名称。若存在多个参数时,需写上对应的参数名,并赋值,如@Subscribe(tag="xx"),若参数为数组类型,则需赋值形如:@Target({ElementType.TYPE,ElementType.METHOD})
5.自定义注解
     从上面的注解中,也大致看到了注解的定义方式。
     1.使用@interface定义一个注解类,其内部自行继承了Annotation类。
     2.在该类中定义注解的参数,定义方式很像方法。
     3.注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。定义一些特殊的值,例如空字符串或者负数,表示某个元素不存在参数设置默认值时,后面跟上default即可设置默认值。
     4.当注解的参数只有一个时,建议用value作为参数名,这样在使用注解时,可以直接写参数的值
     接下来自定义一个注解类:
[java] view plain copy

    @Documented  
    @Target(ElementType.TYPE)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface Car{  
         String name() default "";  
         int number() default -1;  
    }  


再定义一个类去使用这个注解:
[java] view plain copy

    @Car(name="好车",number=666)  
    public class CarBMW(){  
           
    }  


那么如何获取这些注解值呢?有如下的方法:
[java] view plain copy

    if(CarBMW.class.isAnnotationPresent(Car.class)){//判断CarBMW类是否有注解类Car  
         Car carAnnotation=(Car)CarBMW.class.getAnnotation(Car.class);//获取注解实例对象  
         Log.v("Shawn",carAnnotation.name());//获取name参数的值  
         Log.v("Shawn",carAnnotation.number());//获取number参数的值  
    }  

6.Android中的注解
6.1两个常见的注解
Android从API16引入了annotation包,包括两个注解@TargetApi和@SuppressLint
@TargetApi (Build.VERSION_CODES.XX)用于屏蔽某一新api中才能使用的方法报的lint检查出现的错误。
@SuppressLint("NewApi") 屏蔽一切新api中才能使用的方法报的android lint错误

当然,这两个注解的作用仅仅是屏蔽lint错误,在方法中还要判断版本做不同的操作,比如:
[java] view plain copy

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.XX) {  
        //高于XX版本进行的操作  
    } else {  
        //低于XX版本进行的操作  
    }  

6.2Android中用到的注解
API19引入了很多注解,起初是以jar包形式引入的,放在SDK目录下sdk\extras\android\m2repository\com\android\support\support-annotations\
在API21之后,直接放入了annotation包中
Android中的注解分为八类,在API23中有42个注解类

6.2.1 @CallSuper
     要求方法必须调用父类方法,可想而知,Activity的onCreate()方法有此注解标识。
6.2.2 @NonNull和@Nullable     
     定义一个变量或对象可以为空或不可为空,用在方法上表示方法可否返回空。
6.2.3 资源类注解
     @AnimatorRes,@AnimRes,@AnyRes,@ArrayRes,@AttrRes,@ BoolRes,@ ColorRes,@ DimensRes,@ DrawableRes,@ FractionRes,@ IdRes,@ IntegerRes,@ InterpolatorRes,@ LayoutRes,@ MenuRes,@ PluralsRes,@ RawRes,@ StringRes,@ StyleableRes,@StyleRes,@ TransitionRes,@ XmlRes
这部分注解是非常有实用性的,有22个,用法如:
[java] view plain copy

    getDrawable(@DrawableRes int id)  //getDrawable方法限定了传入的参数必须是Drawable资源文件  

另外还有个@ColorInt,限制传入Hex颜色值。
在开发过程中需要传入某种资源文件时,用此类注解,是很有限制作用的做法。
6.2.4@IdDef和@StringDef
提到最常用的Toast,在API21之前,一般可以这么写
Toast.makeText(context, "msg", 0).show();
但是21之后,0突然被划红线了,查看源码发现,之前是这么写的:
[java] view plain copy

    public static final int LENGTH_SHORT = 0;  
    public static final int LENGTH_LONG = 1;  


makeText方法中单纯地写着int duration参数,而21之后,成了这样:
[java] view plain copy

    @IntDef({LENGTH_SHORT, LENGTH_LONG})  
    @Retention(RetentionPolicy.SOURCE)  
    public @interface Duration {}  


在makeText的duration参数之前加上了注解@Duration,这就要求传入Duration中的值才不会报警告。
可以想象,@IntDef和@String Def中放入了一个value数组。
在开发中,这两个注解就可以用来限制枚举值了。

6.2.5 范围约束@FloatRange、@IntRange和@Size
前两个限制了数字的范围,比如可以用来限制传入参数值的范围,
@Size可以用来限定集合的大小或者限定字符串的长度,还可以做其他限制:
1.限制最小最大数量:@Size(min=1,max=10 )
2.数量必须是2的倍数(偶数): @Size(multiple=2)

6.2.6 进程类注解
@UiThread,@BinderThread,@MainThread,@WorkerThread
用来限定方法或类在指定的线程类型中被调用,比如 AsyncTask中的方法就有如下的限定:
[java] view plain copy

    @WorkerThread  
    protected abstract Result doInBackground(Params... params){  
         //doInBackground  
    }  
    @MainThread  
    protected void onProgressUpdate(Progress... values) {  
         //onProgressUpdate  
    }  

6.2.7@CheckResult
该注解意味着需要对方法的返回值进行处理,例如:有个方法为
[java] view plain copy

    @CheckResult  
    public boolean checkValid(String value){  
         return TextUtils.isEmpty(value);  
    }  


当调用者直接调用checkValid("abc");时会报错,这意味着,需要对方法的返回值进行处理,无论返回true或false,需要进行后续操作,不能单单调用一句checkValid("abc");

6.2.8 权限注解@RequiresPermission
如果方法的调用需要权限,可以加这个注解,当需要几个权限中的一个时,使用anyOf,如 @RequiresPermission(anyOf = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})
若需要多个权限,使用allOf,如 @RequiresPermission(allOf = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
若需要单独的标注读和写的权限访问,所以可以用@Read或者@Write标注每一个权限需求
6.2.9 @SdkConstant
表示一个常量字段应该被输出在SDK工具中使用,例如:
添加一个自定义的Action:
[java] view plain copy

    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)   
    public static final String ACTION_MY_TEST = "android.intent.action.MY_TEST";   


则可以这样使用:
[java] view plain copy

    Intent myTest = new Intent(Intent.ACTION_MY_TEST);   
    mContext.sendBroadcast(myTest);  

6.2.10@Widget
用于类的注解,表示该类是自定义的Widget类

此外还有两个注解即上述的@TargetApi和@SuppressLint不再赘述。
7.总结
综上,注解部分就介绍完了。注解在开发过程中有很强的实用性,使用注解可以明确开发过程中的一些数据类型,还可以对一些数据进行限制,从而提高开发效率。


AIDL进程间通信的流程,分为服务端和客户端:
1.服务端
首先需要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可。

2.客户端
首先通过绑定服务端的Service,绑定成功后,将服务端返回的IBinder对象转成AIDL接口所属的类型。接着就可以调用AIDL中的方法了


使用AIDL实现IPC

使用AIDL实现IPC服务的步骤是:

1. 创建.aidl文件-该文件(YourInterface.aidl)定义了客户端可用的方法和数据的接口。

2. 在makefile文件中加入.aidl文件-(Eclipse中的ADT插件提供管理功能)Android包括名为AIDL的编译器,位于tools/文件夹。

3. 实现接口-AIDL编译器从AIDL接口文件中利用Java语言创建接口,该接口有一个继承的命名为Stub的内部抽象类(并且实现了一些IPC调用的附加方法),要做的就是创建一个继承于YourInterface.Stub的类并且实现在.aidl文件中声明的方法。

4. 向客户端公开接口-如果是编写服务,应该继承Service并且重载Service.onBind(Intent) 以返回实现了接口的对象实例

创建.aidl文件
AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。重要的是必须导入所有非内置类型,哪怕是这些类型是在与接口相同的包中。下面是AIDL能支持的数据类型:

1.Java编程语言的主要类型 (int, boolean等) — 不需要 import 语句。

2.以下的类 (不需要import 语句):
0 0
原创粉丝点击