一、前言
我们在安卓开发中,初始学习时我们可能会写findViewById写的想吐,而后来我们可能会使用Xutils或ButterKnife优化findViewById,因此我们基于之前掌握的反射和注解的知识实现 ,在学习本文。
二、优化findViewById和点击事件
(1)创建点击注解类,这里可以传入id集合
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
int[] value();
}
(2)创建绑定id类
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
int value();
}
(3)findViewById类,针对Activity和View区分
/**
* findViewById
*/
public class ViewFinder {
private Activity mActivity;
private View mView;
public ViewFinder(Activity activity) {
mActivity = activity;
}
public ViewFinder(View view) {
mView = view;
}
public View findViewById(int viewId) {
return mActivity != null ? mActivity.findViewById(viewId) : mView.findViewById(viewId);
}
}
(4)工具类,调用此方法,才会将事件进行绑定,可以调用
public class BindUtils {
//绑定至Activity中
public static void bind(Activity activity) {
bind(new ViewFinder(activity), activity);
}
//绑定至View中
public static void bind(View view) {
bind(new ViewFinder(view), view);
}
//绑定至Fragment中
public static void bind(View view, Object object) {
bind(new ViewFinder(view), object);
}
//通用方法
public static void bind(ViewFinder viewFinder, Object object) {
bindFiles(viewFinder, object);
bindMethods(viewFinder,object);
}
//处理点击按钮事件
private static void bindMethods(ViewFinder viewFinder, final Object object) {
//获取Class对象
Class<?> aClass = object.getClass();
//反编译获取所以方法
Method[] methods = aClass.getDeclaredMethods();
if (null!=methods){
for (final Method method : methods) {
//获取Annotation
final OnClick onClick = method.getAnnotation(OnClick.class);
if (null!=onClick){
int[] values = onClick.value();
for (int value : values) {
View view = viewFinder.findViewById(value);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
//解除私有限制
method.setAccessible(true);
//执行点击事件
method.invoke(object,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
//绑定属性
private static void bindFiles(ViewFinder viewFinder, Object object) {
Class<?> aClass = object.getClass();
Field[] fields = aClass.getDeclaredFields();
if (null != fields) {
for (Field field : fields) {
BindView bindView = field.getAnnotation(BindView.class);
if (null != bindView) {
int viewId = bindView.value();
View view = viewFinder.findViewById(viewId);
if (null != view) {
try {
field.setAccessible(true);
field.set(object, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
}
(5)在Activity、View、Fragment中调用BindUtils,这里的布局就是一个文本2个按钮。
public class MainActivity extends AppCompatActivity {
@BindView(R.id.tv_msg)
private TextView mTvMsg;
@OnClick({R.id.btn_click1, R.id.btn_click2})
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_click1:
Toast.makeText(this, "toast1", Toast.LENGTH_SHORT).show();
break;
case R.id.btn_click2:
Toast.makeText(this, "toast2", Toast.LENGTH_SHORT).show();
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BindUtils.bind(this);
mTvMsg.setText("测试BindViw!!!");
}
}
三、扩展
例如我们可以写长按事件,我们还可以在点击前进行网络判断,权限判断申请等操作,根据个人需求进行扩展。
网友评论