Android 注解,实现动态绑定view

之前的一篇文章介绍了什么是注解 (直达链接:点击打开链接


现在有许多开源的注解框架,比如:butterknife/androidannotation等,这些框架能帮助我们大大简化了代码,使我们不用再机械的写这种findViewById, setOnClickListener等方法


接下来就自己用注解,实现了一下view的绑定


1.声明注解 

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface EActivity {
    int value();
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ViewById {
    int value();
}

2.在activity中使用注解 

@EActivity(R.layout.activity_annotation) //绑定布局文件
public class AnnotationActivity extends AppCompatActivity implements View.OnClickListener {

    @ViewById(R.id.text)
    private TextView mTextView;

    @ViewById(R.id.button)
    private Button mButton;

    private int mClickTimes = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //调用注解工具类实现对view的绑定
        AndroidBindViewUtils.startBinding(this);

        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                mClickTimes++;
                mTextView.setText("点击了btn " + mClickTimes + " 次!");
                break;
        }
    }
}

3.如何实现view的绑定

 这里用的是运行时注解,需要借助反射的方式获取到具体的方法,然后和对应的值进行绑定

 

public class AndroidBindViewUtils {

    private static Method sMethodSetContentView;
    private static Method sMethodFindViewById;

    public static void startBinding(Activity activity) {
        bindContentView(activity);
        bindViewById(activity);
    }

    private static void bindContentView(Activity activity) {
        EActivity eActivity = activity.getClass().getAnnotation(EActivity.class);
        if (eActivity != null) {
            int contentviewId = eActivity.value(); //拿到绑定的layout id
            if (sMethodSetContentView == null) {
                getSetContentViewMethod();
            }
            try {
                sMethodSetContentView.invoke(activity, contentviewId); //通过反射调用activity的setContentView方法
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    private static void bindViewById(Activity activity) {
        Field[] fields = activity.getClass().getDeclaredFields();//拿到activity的所有变量
        for (Field field : fields) {
            ViewById viewById = field.getAnnotation(ViewById.class);//通过变量拿到ViewById注解
            if (viewById != null) {
                int id = viewById.value();//拿到具体的view id
                try {
                    if (sMethodFindViewById == null) {
                        getFindViewByIdMethod();
                    }
                    Object view = sMethodFindViewById.invoke(activity, id); //通过反射findViewById获取具体的view
                    field.setAccessible(true);
                    field.set(activity, view);//把这个view赋值给field变量
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void getSetContentViewMethod() {
        if (sMethodSetContentView == null) {
            try {
                sMethodSetContentView = Activity.class.getDeclaredMethod("setContentView", int.class);
                sMethodSetContentView.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

    private static void getFindViewByIdMethod() {
        if (sMethodFindViewById == null) {
            try {
                sMethodFindViewById = Activity.class.getDeclaredMethod("findViewById", int.class);
                sMethodFindViewById.setAccessible(true);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值