/**
* Created by halong on 2018/1/14.
* 反射应用的主要步骤:
* 1,获取目标对象
* 2,根据目标对象获取对应类
* 3,获取所有属性或者方法
* 4,轮询找到自定义注解标记的属性或方法
* 5,对目标属性或者方法进行操作 get set invoke
*/
public class ViewFinder {
public static void bind(Activity activity){ //通过参数可获取目标对象 即属性所属的对象
Class activityClass=activity.getClass();//获取响应的类->Class.forName(),Object.getClass()
Field[] fields=activityClass.getDeclaredFields();
//getDeclaredFields()->获取所有的fields
// getFields()->值获取public fields
for (Field field : fields) { //for each轮询
//剔除被static ,final 修饰的field
if(Modifier.isStatic(field.getModifiers())||Modifier.isFinal(field.getModifiers())){
continue;//continue->跳出当前,进入下一循环。break->直接跳出所有循环
}
// A.class.isAssignableFrom(B.class); ->判断A是否是B类的父类或者同一类
//对象 instance of 类
// Logger.d(TextView.class.isAssignableFrom(View.class));//false
// Logger.d(View.class.isAssignableFrom(View.class));//true
// Logger.d(View.class.isAssignableFrom(TextView.class));//true
//剔除非View子类的field
if(!View.class.isAssignableFrom(field.getType())){
continue;
}
//找到注解指定的field
FindView annotation=field.getAnnotation(FindView.class);
if (annotation!=null){
int id=annotation.value();//获取注解传入的参数
View view =activity.findViewById(id);
field.setAccessible(true); //对于getDeclaredXX()要使用setAccessible(true);
try {
field.set(activity,view);//对该属性赋值
//field.set(所属的对象,赋的值)
// field.get(所属对象) 得到所属对象中的对应属性值
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 定义注解:
* 主要作用是:1,标记目标->FindView annotation=field.getAnnotation(FindView.class);
* 2,传入参数->int id=annotation.value();->获取到id
*/
@Retention(RetentionPolicy.RUNTIME)//作用时间范围 默认CLASS
//反射的标记注解必须RUNTIME
@Target(ElementType.FIELD) //作用类型 默认所有
// ElementType.FIELD->属性
//ElementType.METHOD->方法
//ElementType.CONSTRUCTOR->构造方法
//ElementType.PARAMETER->参数
//ElementType.LOCAL_VARIABLE->变量
//ElementType.PACKAGE->包
//ElementType.ANNOTATION_TYPE->注解
//ElementType.TYPE->
public @interface FindView {
int value();//传入参数
}
/**
* 测试反射:
*/
public class ViewFinderActivity extends AppCompatActivity {
@FindView(R.id.textView)
private TextView textView;
@FindView(R.id.textView)
private static TextView textView2; //测试非法修饰 如果success->忽视 failure->throw exception
@FindView(R.id.textView)
private String textView3;//测试非法指定的field类型 如果success->忽视 failure->throw exception
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_finder);
ViewFinder.bind(this);
textView.setText("hello");
}
}