通过注解达到setContentView和findViewById的目的

//Retention有三种策略
1.RetentionPolicy.CLASS 只在字节码起效果
2.RetentionPolicy.SOURCE 只在编译期间效果,起标识作用
3RetentionPolicyRUNTIME 运行时起作用,一般用于反射

//Target表示该注解的作用域
ElementType.FIELD 表示可以作用在成员属性上
ElementType.METHOD表示该注解可以作用在成员方法上
ElementType.TYPE表示该注解可以作用在类或接口上
当需要作用在多个作用域时可以通过@Target({ ElementType.FILD , ElementType.METHOD , ElementType.CLASS })

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ContentView{
    int value();//当只有一个属性时,只能起value这个名字,此时获取注解的值时也不需要用ContentView(value = 123),而是直接使用BindView(123),int表示value接收的数据类型。
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface BindView {
    int value();
}
@ContentView(R.layout.activity_main) //该注解的作用是给该类设置一个布局文件,其功能和setContentView一样,下面介绍实现
public class MainActivity extends Activity{

    @BindView(R.id.tv_title) //给title设置一个控件,其功能和findViewById功能一样,下面介绍
    private TextView title;

    @BindView(R.id.iv_icon)
    private ImageView icon;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        ViewInject.inject(this);
        title.setText("测试");
        icon.setBackgroundResource(R.drawable.ic_head_bg);

    }
}
public class ViewInject {

    public static void inject(Activity activity) {
        Class<? extends Activity> activityClass = activity.getClass();//通过对象获取Class
        if (activityClass.isAnnotationPresent(ContentView.class)) { //判断该类上有没ContentView这个注解,有就返回true,否则返回false
            ContentView annotation = activityClass.getAnnotation(ContentView.class);//获取ContentView这个注解
            int value = annotation.value();//获取注解上的值
            try {

                //此处只能用getMethod而不能用getDeclaredMethod方法
                //getMethod方法只能获取public类型的方法包括父类的,而getMethod能获取private、protected、public、default类型的方法,但是不能获取父类的方法
                //而此处的setContentView方法是父类的,故只能使用getMethod
                Method method = activityClass.getMethod("setContentView", int.class);//获取形参为int类型的setContentView这个方法,
                method.setAccessible(true);//暴力访问,如果不设置将不能访问private修饰的成员
                method.invoke(activity, value);//调用activity这个对象的method方法,该方法的参数为value
                Log.i("TAG", "inject");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        Field[] fields = activityClass.getDeclaredFields();//获取本类中所有字段,包括private、protected、default、public,但不包括父类的
        for(Field field : fields){
            if(field.isAnnotationPresent(BindView.class)){//判断该类上是否有BindView这个注解
                BindView annotation = field.getAnnotation(BindView.class);//获取这个字段的BindView注解
                int value = annotation.value();//获取这个注解的值
                try {
                    Method method = activityClass.getMethod("findViewById", int.class);获取这个类中的findViewById方法
                    method.setAccessible(true); //由于findViewById是public类型的,故此处可以不调用该方法

                    int resultView = (int)method.invoke(activity, value);//方法调用后会有一个返回结果
                    field.setAccessible(true); //此处一定要使用,否则将不能访问field字段,因为很多时候我们都会把View设置为private访问权限
                    field.set(activity, resultView);

                    Log.i("TAG", "success4");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楚蕊博南谭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值