Android 之动态代理

先不说话

Class LogHandler

执行统一操作

 

获取方法注解,获取参数注解

 

获取参数的值

Interface LogUtil

定义方法,做方法注解,做参数注解

 

 

 

 

Parms

参数注解

 

 

 

 

Method

方法注解

 

 

 

 





1.Params 注解

package com.sclgxt.invokeapplication;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**  * Created by Sclgxton 2016/5/5.  */ @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Params {
    String value() default "";
}
2.Method注解

package com.sclgxt.invokeapplication;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**  * Created by Sclgxt on 2016/5/5.  */ @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Tag {
    String value() default "";
}
3.CallBack
package com.sclgxt.invokeapplication;

/**  * Created by Sclgxt on 2016/5/5.  */ public interface CallBack {
    void log(String message);
}

4.LogUtil

package com.sclgxt.invokeapplication;

/**  * Created by Sclgxt on 2016/5/5.  */ public interface LogUtil {
    @Tag("男神")
    void print(@Params("Name") String message, CallBack callBack);

    @Tag("女神")
    void print(@Params("Name") String name, @Params("Age") String age, CallBack callBack);
}
5.LogHandler

package com.sclgxt.invokeapplication;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**  * Created by Dell on 2016/5/5.  */ public class LogHandler<T> {
    private static LogHandler logPrint;
    private static Map<String, Object> map = new HashMap<>();

    private LogHandler() {

    }

    public static LogHandler getInstance() {
        if (logPrint == null) {
            logPrint = new LogHandler();
        }
        return logPrint;
    }

    public LogUtil create(Class mclass) {
        /**  * 缓存中去  */  Object o = null;
        map.get(mclass);
        /**  * 取不到则取构造代理对象  */  if (o == null) {
            o = Proxy.newProxyInstance(LogHandler.class.getClassLoader(), new Class[]{mclass}, new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    final CallBack callback = (CallBack) args[args.length - 1];


                    final Tag tag = method.getAnnotation(Tag.class);
                    if (tag != null) {
                        /**  * 获得方法注解的值  */  StringBuilder tagvalue = new StringBuilder();
                        tagvalue.append(tag.value());
                        tagvalue.append("\n");
                        System.out.println(tagvalue.toString());
                        /**  * 获得所有参数上的注解  */  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) {
                                        /**  * 如果是Params注解  */  if (methodParameterAnnotation instanceof Params) {
                                            /**  * 取得Params注解上的值  */  Params paramsinterface = (Params) methodParameterAnnotation;
                                            String paramsvalue = paramsinterface.value();
                                            System.out.println(paramsvalue);

                                            /**  * 这是对应的参数的值  */  tagvalue.append(paramsvalue + ": ");
                                            System.out.println(args[i]);
                                            tagvalue.append(args[i]);
                                            tagvalue.append("\n");

                                            /**  * 使用Params注解替换get注解中的值为参数值  */  }
                                    }
                                }

                            }
                        }
                        callback.log(tagvalue.toString());
                    }
                    return null;
                }
            });
            map.put(mclass.toString(), o);
        }
        return (LogUtil) o;
    }
}
6.使用

final TextView tv = (TextView) findViewById(R.id.view);
LogUtil logUtil = LogHandler.getInstance().create(LogUtil.class);
logUtil.print("林允儿", "22", new CallBack() {
    @Override
    public void log(String message) {
        tv.setText(message);
        Log.i("", "-->" + message);
    }
});
logUtil.print("郭碧婷", new CallBack() {
    @Override
    public void log(String message) {
        tv.setText(tv.getText() + "\n" + message);
        Log.i("", "-->" + message);
    }
});
7.效果


8.为什么这么写,为了那些虽然参数不同,方法名也不尽相同,但是它们都执行统一的操作的方法,我感觉这就是为了装逼,因为我们总有其他方法来实现;

    第一次看见的时候,是在一个同事写的网络请求之中:给你们贴一段代码

    NetUtil

//请求验证码 @POST("/api/common/queryCode")
NetRequest getCode(@PARAMS("mobile") String mobile, @PARAMS("type") int type);

//请求用户信息 @POST("/api/user/queryInfo")
NetRequest<UserInfo> queryInfo(@PARAMS("sign") String sign);


//登录 @POST("/api/user/login")
NetRequest<User> login(
        @PARAMS("code") String code,
        @PARAMS("network") int network,
        @PARAMS("brand") String brand,
        @PARAMS("lat") double lat,
        @PARAMS("lng") double lng,
        @PARAMS("brandId") String brandId,
        @PARAMS("ostype") int ostype,
        @PARAMS("osversion") String osversion,
        @PARAMS("maptype") String maptype,
        @PARAMS("countryCode") String countryCode,
        @PARAMS("register_channel") String register_channel
);
就这样,通过和后台商量好数据返回格式,再知道返回数据类型,就可以轻易的得到自己想要的各种class 数据,当然我们还有其他的实现方式,总之我还是觉得这是装逼!!!!!!!之前1-6的代码,拷贝下来可以运行,原理就不说了,自己想去!!
Proxy.newProxyInstance()这个方法的第一个参数,ClassLoder 没什么作用....

你可能感兴趣的:(Android 之动态代理)