Android 개발 에서 자주 사용 하 는 디자인 모델 - 동적 에이전트 모델

14915 단어 기술 지식
동적 프 록 시 모드 가 자바 WEB 에서 의 응용 은 어디서나 볼 수 있 습 니 다. 특히 spring 프레임 워 크 에서 동적 프 록 시 를 대량으로 사 용 했 습 니 다.가장 중요 한 디자인 모델 이자 가장 이해 하기 어 려 운 디자인 모델 중 하나 라 고 할 수 있다.
그럼 동적 대리 가 뭐 죠?
프 록 시 클래스 는 프로그램 이 실행 되 기 전에 존재 하지 않 고 실행 할 때 프로그램 이 동적 으로 생 성 하 는 프 록 시 방식 을 동적 프 록 시 라 고 합 니 다.
현재 의 네트워크 요청 라 이브 러 리 는 다양 하 다. 그 중에서 Square 회사 의 OkHttp 는 완벽 한 네트워크 요청 라 이브 러 리 이 고 그 위 에 Retrofit 라 이브 러 리 를 포장 하여 Restful Api 를 편리 하고 신속하게 호출 하 는 데 지름길 을 제공 했다.만약 당신 이 Retrofit 를 사용 한 적 이 있다 면, 이러한 과정 이 있 을 것 이라는 것 을 잊 지 않 을 것 입 니 다.
4. 567917. 먼저 인 터 페 이 스 를 정의 하고 인터페이스 에서 네트워크 요청 의 구체 적 인 방법 을 정의 하 며 방법 적 으로 host, header, params 등 정 보 를 주석 으로 설정 합 니 다
4. 567917. 그리고 Retrofit 대상 을 새로 만 들 고 이 대상 을 통 해 당신 이 정의 하 는 인터페이스 대상 을 만 듭 니 다
4. 567917. 인터페이스 대상 을 통 해 구체 적 인 방법 으로 요청 을 완성 합 니 다
이렇게:

public interface GitHubService {
  @GET("users/{user}/repos")
  Call> listRepos(@Path("user") String user);

}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .build();


GitHubService service = retrofit.create(GitHubService.class);

Call> repos = service.listRepos("octocat");

그렇다면 인터페이스 가 직접 new 로 나 올 수 없다 는 문 제 를 생각해 본 적 이 있 습 니까? GitHubService 인터페이스의 인 스 턴 스 는 어떻게 생 겼 습 니까? retrofit. create 방법 내부 에서 무엇 을 했 습 니까?맞 아, 답 은 동적 대리 야.이 대상 은 프로그램 실행 기간 에 생 성 된 에이전트 대상 입 니 다.
동적 에이 전 트 는 자바 WEB 에서 대량으로 사용 되 지만 클 라 이언 트 에 서 는 성능 문 제 를 고려 하여 동적 에이 전 트 를 사용 할 때 신중하게 고려 하지만 동적 에이 전 트 를 잘 사용 하면 다른 효과 가 발생 합 니 다. 예 를 들 어 이 Retrofit 라 이브 러 리 등 입 니 다.다음은 Retrofit 의 가장 간단 하고 쉬 운 버 전 을 실현 합 니 다.동적 에이전트 의 원 리 를 살 펴 보 자.간이 판이 기 때문에 많은 것들 이 리 트 로 핏 과 차이 가 있 고 리 트 로 핏 만큼 편리 하지 않다 는 점 을 무시 하면 된다.우 리 는 위의 그 예 를 실현 하 는 것 을 예 로 들 자.
먼저 한 가지 설명 하 자 면, 우리 의 요 구 는 비동기 적 이기 때문에, 반환 값 은 void 를 사용 하고, 리 셋 파 라미 터 를 추가 하 며, 마지막 파 라미 터 는 리 셋 이 라 고 약속한다.


public interface Callback {

    void onSuccess(Object t);

    void onFailed(Exception e);

}

최종 인터페이스 정 의 는 이 럴 것 이다.

public interface GithubService {

    @GET("users/{user}/repos")

    void listRepos(@Path("user") String user,Callback> callback);

    /**

     *          callback

     */

}

두 개의 주 해 를 사 용 했 는데 하 나 는 방법 주해 이 고 하 나 는 매개 변수 주해 이다.

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD})

public @interface GET {

    String value() default "";

}

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.PARAMETER)

public @interface Path {

    String value();

}

Repo 실체 클래스 는 json 에 따라 GsonFormat 을 사용 하여 자동 으로 생 성 됩 니 다.
그 다음 에 우 리 는 Retrofit 류 를 작 성 했 습 니 다. 이 종 류 는 builder 모드 일 것 입 니 다. 그 안에 baseUrl 을 설정 할 수 있 고 다른 모든 인 자 를 무시 할 수 있 습 니 다.create 방법 이 하나 더 있 습 니 다. 원형 은 다음 과 같 습 니 다.
public class Retrofit {

    private String baseUrl;
    private Retrofit(Builder builder) {
        this.baseUrl = builder.baseUrl;
    }

    public  T create(Class clazz) {
        return null
    }

    static class Builder {
        private String baseUrl;
        Builder baseUrl(String host) {
            this.baseUrl = host;
            return this;
        }

        Retrofit build() {
            return new Retrofit(this);
        }
    }
}

가장 중요 한 내용 은 create 방법의 실현 이다.원 리 는 먼저 마지막 매개 변수, 즉 리 셋 을 받 은 다음 에 방법 상의 주 해 를 받 아 구체 적 인 값 을 얻 은 다음 에 리 셋 을 제외 한 다른 매개 변 수 를 받 아 매개 변수 상의 주 해 를 얻 은 다음 에 주해 에 따라 대응 하 는 값 을 얻 고 원래 의 매개 변수 값 을 얻어 방법 상의 주해 의 값 을 교체 하 는 것 이다.OkHttp 구조 요청 을 사용 합 니 다. 요청 이 완료 되면 결 과 를 리 셋 의 형식 으로 해석 합 니 다.전체 과정 은 다음 과 같다.
public  T create(Class clazz) {
        /**
         *     
         */
        Object o = serviceMap.get(clazz);
        /**
         *            
         */
        if (o == null) {
            o = (T) Proxy.newProxyInstance(Retrofit.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    final Callback> callback = (Callback>) args[args.length - 1];


                    final GET get = method.getAnnotation(GET.class);
                    if (get != null) {
                        /**
                         *   GET    
                         */
                        String getValue = get.value();

                        System.out.println(getValue);

                        /**
                         *           
                         */
                        Annotation[][] methodParameterAnnotationArrays = method.getParameterAnnotations();

                        if (methodParameterAnnotationArrays != null) {
                            int count = methodParameterAnnotationArrays.length;
                            for (int i = 0; i < count; i++) {
                                /**
                                 *           
                                 */
                                Annotation[] methodParameterAnnotations = methodParameterAnnotationArrays[i];

                                if (methodParameterAnnotations != null) {
                                    for (Annotation methodParameterAnnotation : methodParameterAnnotations) {

                                        /**
                                         *    Path  
                                         */
                                        if (methodParameterAnnotation instanceof Path) {

                                            /**
                                             *   path     
                                             */
                                            Path path = (Path) methodParameterAnnotation;
                                            String pathValue = path.value();
                                            System.out.println(pathValue);

                                            /**
                                             *          
                                             */
                                            System.out.println(args[i]);


                                            Request.Builder builder = new Request.Builder();


                                            /**
                                             *   path    get         
                                             */
                                            String result = getValue.replaceAll("\\{" + pathValue + "\\}", (String) args[i]);

                                            System.out.println(result);

                                            /**
                                             *       
                                             */
                                            Request request = builder.get()
                                                    .url(baseUrl + "/" + result)
                                                    .build();

                                            okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
                                                @Override
                                                public void onFailure(Call call, IOException e) {
                                                    /**
                                                     *           
                                                     */
                                                    callback.onFailed(e);
                                                }

                                                @Override
                                                public void onResponse(Call call, Response response) throws IOException {
                                                    if (response.isSuccessful()) {
                                                        /**
                                                         *     
                                                         */
                                                        String body = response.body().string();

                                                        /**
                                                         *   fastjson  zhuan  
                                                         */
                                                        Type type = callback.getClass().getGenericInterfaces()[0];

                                                        Object o1 = JSON.parse(body);

                                                        /**
                                                         *     
                                                         */
                                                        callback.onSuccess(o1);
                                                    }
                                                }
                                            });

                                        }
                                    }
                                }

                            }
                        }
                    }


                    return null;
                }
            });
            /**
             *      
             */
            serviceMap.put(clazz, o);
        }
        return (T) o;
    }

그리고 우 리 는 Retrofit 에 따라 호출 할 수 있 습 니 다.
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com")
        .build();

GithubService githubService = retrofit.create(GithubService.class);

githubService.listRepos("lizhangqu", new Callback>() {
    @Override
    public void onSuccess(Object t) {
        System.out.println(t);
    }
    @Override
    public void onFailed(Exception e) {
    }
});

이것 은 Retrofit 에서 가장 간단 한 모듈 로 이 루어 진 것 입 니 다. 다른 내용 에 관심 이 있 으 면 retrofit 의 소스 코드 를 읽 을 수 있 습 니 다.

좋은 웹페이지 즐겨찾기