Android 注解快速入门和实用解析

首先什么是注解?@Override就是注解,它的作用是:

1、检查是否正确的重写了父类中的方法。 
2、标明代码,这是一个重写的方法。

1、体现在于:检查子类重写的方法名与参数类型是否正确;检查方法private/final/static等不能被重写。实际上@Override对于应用程序并没有实际影响,从它的源码中可以出来。

2、主要是表现出代码的可读性。

作为Android开发中熟知的注解,Override只是注解的一种体现,更多时候,注解还有以下作用:

  • 降低项目的耦合度。
  • 自动完成一些规律性的代码。
  • 自动生成java代码,减轻开发者的工作量。

一、注解基础快读

1、元注解

元注解是由java提供的基础注解,负责注解其它注解,如上图Override被@Target@Retention修饰,它们用来说明解释其它注解,位于sdk/sources/android-25/java/lang/annotation路径下。

元注解有:

  • @Retention:注解保留的生命周期
  • @Target:注解对象的作用范围。
  • @Inherited:@Inherited标明所修饰的注解,在所作用的类上,是否可以被继承。
  • @Documented:如其名,javadoc的工具文档化,一般不关心。

@Retention

Retention说标明了注解被生命周期,对应RetentionPolicy的枚举,表示注解在何时生效:

  • SOURCE:只在源码中有效,编译时抛弃,如上面的@Override
  • CLASS:编译class文件时生效。
  • RUNTIME:运行时才生效。

如下图X1,com.android.support:support-annotations中的Nullable注解,会在编译期判断,被注解的参数是否会空,具体后续分析。

@Target

Target标明了注解的适用范围,对应ElementType枚举,明确了注解的有效范围。

  • TYPE:类、接口、枚举、注解类型。
  • FIELD:类成员(构造方法、方法、成员变量)。
  • METHOD:方法。
  • PARAMETER:参数。
  • CONSTRUCTOR:构造器。
  • LOCAL_VARIABLE:局部变量。
  • ANNOTATION_TYPE:注解。
  • PACKAGE:包声明。
  • TYPE_PARAMETER:类型参数。
  • TYPE_USE:类型使用声明。

如上图X1所示,@Nullable可用于注解方法,参数,类成员,注解,包声明中,常用例子如下所示:

 /**
   * Nullable表明
   * bind方法的参数target和返回值Data可以为null
   */
  @Nullable 
  public static Data bind(@Nullable Context target) {
    //do someThing and return
    return bindXXX(target);
  }

@Inherited

注解所作用的类,在继承时默认无法继承父类的注解。除非注解声明了 @Inherited。同时Inherited声明出来的注,只对类有效,对方法/属性无效。

如下方代码,注解类@AInherited声明了Inherited ,而注解BNotInherited 没有,所在在它们的修饰下:

  • 类Child继承了父类Parent的@AInherited,不继承@BNotInherited
  • 重写的方法testOverride()不继承Parent的任何注解;
  • testNotOverride()因为没有被重写,所以注解依然生效。

继续阅读全文 “Android 注解快速入门和实用解析”

Retrofit-Android上的token验证

这篇文章是一个除了前面的帖子使用retrofit进行基本的身份验证和使用基于OAuth的基本APIS。我们将讨论的话题token认证从一个Android应用到任何网络服务或API支持这种认证。

Integrate Token Authentication

如果你读前面的帖子关于使用retrofit的身份验证,你会猜到我们要怎么做:扩展ServiceGenerator类和集成方法处理token认证。让我们直接与第二个扩展ServiceGenerator createService方法:

Retrofit 1.9

public class ServiceGenerator {

    public static final String API_BASE_URL = "https://your.api-base.url";

    private static RestAdapter.Builder builder = new RestAdapter.Builder()
                .setEndpoint(API_BASE_URL)
                .setClient(new OkClient(new OkHttpClient()));

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null);
    }

    public static <S> S createService(Class<S> serviceClass, final String authToken) {  
      if (authToken != null) {
          builder.setRequestInterceptor(new RequestInterceptor() {
              @Override
              public void intercept(RequestFacade request) {
                  request.addHeader("Authorization", authToken);
              }
          });
      }

      RestAdapter adapter = builder.build();
      return adapter.create(serviceClass);
    }
}

Retrofit 2

public class ServiceGenerator {

    public static final String API_BASE_URL = "https://your.api-base.url";

    private static OkHttpClient httpClient = new OkHttpClient();
    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null);
    }

    public static <S> S createService(Class<S> serviceClass, final String authToken) {
        if (authToken != null) {
            httpClient.interceptors().clear();
            httpClient.interceptors().add(new Interceptor() {
                @Override
                public Response intercept(Interceptor.Chain chain) throws IOException {
                    Request original = chain.request();

                    // Request customization: add request headers
                    Request.Builder requestBuilder = original.newBuilder()
                            .header("Authorization", authToken)
                            .method(original.method(), original.body());

                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            });
        }

        Retrofit retrofit = builder.client(httpClient).build();
        return retrofit.create(serviceClass);
    }
}

正如你所看到的,我们通过身份验证标记作为一个字符串变量方法,使用RequestInterceptor(Interceptor in Retrofit 2)设置HTTP标头字段进行授权。如果你使用另一个HTTP报头字段为您的身份验证token,上面的代码调整或创建一个新的方法处理所需的功能。

从现在开始,每一个HTTP客户端创建该方法集成了令牌授权头字段的值,并自动传递token值与任何请求API端点。

Example Usage

让我们创建一个例子,看看一些代码。下面的UserService接口声明一个方法叫me()。这个示例方法返回一个用户对象从API创建响应。

Retrofit 1.9

public interface UserService {  
    @POST("/me")
    User me();
}

Retrofit 2

public interface UserService {  
    @POST("/me")
    Call<User> me();
}

要特殊照顾调用API等待在终点HTTP任何要求://your.api-base.url/me并要求身份验证以获取用户数据的响应。现在,让我们创建一个用户服务对象,做实际的请求 .

Retrofit 1.9

UserService userService =  
    ServiceGenerator.create(UserService.class, "auth-token");
User user = userService.me();

Retrofit 2

UserService userService =  
    ServiceGenerator.create(UserService.class, "auth-token");
Call<User> call = userService.me();  
User user = call.execute().body();

这段代码演示了如何使用了类。当然,你必须要经过实际验证token值ServiceGenerator方法。

翻译:itxuye  英文原文: futurestud.io