自定义注解实战,自己写一个FindViewById注解

前言

在开发过程中,我们肯定会用到各种三方框架。在安卓开发中,有很多我们国人编写的优秀框架,Afinal,Zfinnal,Xutils等。这些框架功能非常强大。这里我们来说一下主题,在这些框架中我们可以发现都有绑定控件id的功能。也就是通过注解省略FindViewById的过程。近两年也有专门做这一种事的框架,如ButterKnife、dagger2等。那么这个看似有点高科技的功能是怎么实现的呢?今天我就来带大家一步一步自己做一个FindViewById的注解。另外。本文的阅读群体是掌握安卓基本开发的入门级工程师。阅读本文之前需要了解的相关知识有Java反射基础知识与常用API、Java注解的相关知识。现在,我们开始写一个Demo!

1)我们先创建一个新的Android工程。过程我不在叙述。创建好安卓工程后。看一下目录结构。这里我建了一个tools包。来存放相关的类与注解。










2)既然用到注解,我们首先要创建个注解,下面贴上我的代码。

@Target(ElementType.FIELD) //注解目标为域
@Retention(RetentionPolicy.RUNTIME) //运行时注解
public @interface BindView {
    int value() default 0;//当前注解只需要一个值,所以我们用value 默认值为0
}
这里我创建了一个名为BindView的注解,使用了默认的成员value并赋默认值为0,通过元注解限定了该注解的目标范围和作用时间

3)注解类创建好了之后。我们该去使用这个注解了。

在使用这个注解之前,我们先思考一个问题。属性注解在使用的时候是需要通过反射获取属性实例并赋值的,我们在给View赋值的时候每次都需要做反射等操作。那么我们每次使用的时候都需要把这些代码重新写一遍么?答案肯定是NO,所以在这里我们将这个过程抽取出来。这里,我创建了一个InitBindView的类。在这个类中写了一个使用反射为view赋值的方法。下面我贴上代码。

public class InitBindView {


    public static void initBindView(Activity activity) {

        try {

            Class<Activity> clazz = (Class<Activity>) activity.getClass();//通过getClass拿到activity实例
            Field[] fields = clazz.getDeclaredFields();//通过反射拿到类内属性
            //循环取出属性
            for (Field field : fields) {
                if (field.isAnnotationPresent(BindView.class)) {//判断属性是否使用注解
                    BindView inject = field.getAnnotation(BindView.class);//如果使用就获得该类上注解
                    int id = inject.value();
                    if (0 != id) {
                        field.setAccessible(true);//提高反射速度
                        field.set(activity, activity.findViewById(id));//给被注解属性赋值
                    }
                }
            }

        } catch (Exception e) {
            //捕获异常后处理
        }

    }

}

通过注释我们可以了解到在这个方法中我们都做了哪些操作。简述一下就是通过反射拿到Activity中属性,判断是否使用了注解,如果使用,取出注解value并复制给view

4)准备工作已经做好我们来开始使用这个注释吧。直接看代码。

public class MainActivity extends AppCompatActivity {


    @BindView(R.id.tv_annotation)
    private TextView tvAnnotation;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        InitBindView.initBindView(this);

        tvAnnotation.setText("Hello Annotation!!!");
    }
}

在这个Activity的布局中,只有一个TextView,id为tv_annotation,我们通过InitBindView类中的静态方法先做反射的初始化操作,将Activity实例传入。然后通过BindView注解给View赋值,省去了FindViewById的过程。然后我们给这个TextView设置文本 Hello Annotation!!! 我这里截图一张来看下运行结果吧。



可以看到,我们已经成功使用BindView注解绑定了控件与id。

下面我附上项目地址。

https://github.com/JingbinChow/BindViewAnnotation



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Android 自定义列表适配器的示例代码: 1. 首先,在布局文件中定义列表项的布局,例如 list_item.xml: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="16dp"> <ImageView android:id="@+id/item_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/item_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="16dp" android:textSize="16sp" android:textColor="#000000" android:text="Item Name" /> </LinearLayout> ``` 2. 创建一个继承自 BaseAdapter 的自定义适配器类,例如 MyListAdapter: ```java public class MyListAdapter extends BaseAdapter { private Context mContext; private List<MyListItem> mItems; public MyListAdapter(Context context, List<MyListItem> items) { mContext = context; mItems = items; } @Override public int getCount() { return mItems.size(); } @Override public Object getItem(int position) { return mItems.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(mContext); View itemView = convertView; if (itemView == null) { itemView = inflater.inflate(R.layout.list_item, parent, false); } MyListItem item = mItems.get(position); ImageView imageView = (ImageView) itemView.findViewById(R.id.item_image); imageView.setImageResource(item.getImageResId()); TextView textView = (TextView) itemView.findViewById(R.id.item_text); textView.setText(item.getText()); return itemView; } } ``` 3. 在 Activity 中使用自定义适配器,例如 MainActivity: ```java public class MainActivity extends AppCompatActivity { private ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.list_view); List<MyListItem> items = new ArrayList<>(); items.add(new MyListItem(R.drawable.item1, "Item 1")); items.add(new MyListItem(R.drawable.item2, "Item 2")); items.add(new MyListItem(R.drawable.item3, "Item 3")); MyListAdapter adapter = new MyListAdapter(this, items); mListView.setAdapter(adapter); } private static class MyListItem { private int imageResId; private String text; public MyListItem(int imageResId, String text) { this.imageResId = imageResId; this.text = text; } public int getImageResId() { return imageResId; } public String getText() { return text; } } } ``` 这样,就可以自定义一个简单的列表适配器,并在 Activity 中使用它来显示列表项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值