用注解来省略findViewById

在写项目的时候,在引入XUtils后,有一个类ViewUtils,在Activity加入ViewUtils.inject(this),就可以直接View及其子类加上注解就可以省略多行findViewById的操作.

本文是仿这个使用的代码实现,共两个类几十行代码,注释我放入到代码里

第一个注解类:ViewInject,为的是成员变量与资源ID有所关联,代码如下:

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)//表示是在成员变量上使用
public @interface ViewInject {
    int value() default -1;
}

第二个工具类:ViewUtil,提供inject方法,代码如下:

import android.app.Activity;
import android.view.View;

import com.midas.viewinject.annotation.ViewInject;//改成相应的包名

import java.lang.reflect.Field;

public class ViewUtil {
    public static void inject(Activity activity) {
        //遍历activity里成员变量 用getFields不能获取private成员
     Field[] fields = activity.getClass().getDeclaredFields();
        for (Field field : fields) {
            //筛选 对合适的条件(Viewject的注解值和View的子类) 进行findViewByID的操作
       ViewInject annotation = field.getAnnotation(ViewInject.class);
             /* Class.isAssignableFrom()是用来判断一个类Class1和另一个类Class2是否相同或是另一个类Class2的父类或接口。
            格式为:Class1.isAssignableFrom(Class2)*/
            int resID = -1;//??? 此处有点小问题:资源id是自动生成,其取值范围为多少?是否可能为-1?
            if (View.class.isAssignableFrom(field.getType()) && annotation != null && (resID = annotation.value()) != -1) {
                //暴力反射,为的是能给privatefield也能赋值
         if (!field.isAccessible())
                    field.setAccessible(true);
                //field对应的对象赋值
         try {
                    field.set(activity, activity.findViewById(resID));
                } catch (IllegalAccessException e) {
                    //这里异常最有可能就是类型传换失败,最好在此用Log进行捕捉
           e.printStackTrace();
                }
            }
        }
    }
}

在Activity中的使用此方法的例子,代码片段如下:
public class MainActivity extends AppCompatActivity {
    @ViewInject(R.id.tv_show)
    private TextView tv_show;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewUtil.inject(this);
        tv_show.setText("调用反射成功");
    }
}

此文主要提供一种实现思路,在上述代码有不完善之处还请指正,另希望有人此答疑: 资源ID(也就是R.id.xxx)取值范围为多少?


你可能感兴趣的:(android开发代码)