使用注解和反射干掉繁复的findViewById
在实际开发中,会经常使用到findViewById获取控件,但是业务一旦复杂起来,难免满屏都是findViewById代码,功能类似,繁复。那有没有办法避免写一大堆的findViewById代码呢?答案肯定是有的。开源框架butterknife、ViewBinding、DataBin ding等都可以彻底解决这个问题。如果仅仅只是干掉findViewById,显得有点大材小用了。现在我们基于butterknife原理实现替代findViewById的工具类。
首先,我们需要定义一个注解。由于是作用于成员变量的,所以@Target值应该为ElementType.FIELD。要实现在运行时获取到控件ID并且赋值的目的,则@Retention必须为RetentionPolicy.RUNTIME。由于value()只接受控件ID,所以应该给value()加上@IdRes声明。具体代码如下:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewFinds {
@IdRes int value();
}
定义好了注解之后,我们还需要定义工具类。这里我们仅仅以Activity为例子:
public class ViewFindUtil {
public static void find(Activity activity) {
Class<? extends Activity> cls = activity.getClass();
//获得此类的所有成员变量
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
//需要判断当前属性是否被ViewFinds注解声明
if (field.isAnnotationPresent(ViewFinds.class)) {
//获取到注解信息
ViewFinds viewFinds = field.getAnnotation(ViewFinds.class);
//获取到控件ID
int viewId = viewFinds.value();
//获取到控件
View view = activity.findViewById(viewId);
//反射设置属性的值
//设置访问权限,允许操作private的属性
field.setAccessible(true);
try {
//赋值
field.set(activity, view);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
现在注解和工具类都定义好了,我们来试试效果。先定义一个页面activity_main和一个MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@ViewFinds(R.id.btn_ok)
private Button btn_ok;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewFindUtil.find(this);
btn_ok.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Toast.makeText(this, "Success!", Toast.LENGTH_SHORT).show();
}
}
最终测试成功,图片就不贴出来了。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。