android的依赖注入
来源:互联网 发布:tc21弓坯淘宝 编辑:程序博客网 时间:2024/06/16 05:26
这几年针对Android推出了不少View注入框架,例如ButterKnife。我们首先来了解一下使用这些框架有什么好处,其实好处很明显:它可以减少大量的findViewById以及setOnClickListener代码,简化了代码,让我们的代码看起来条理更清晰,可读性变强。
可能大多数对于这一类框架,都只是停留在用的阶段,但是作为一个程序员,我们有必要去了解它是如何实现的。其实它的原理也没有多复杂,用到了Java中反射和注解的相关知识,所以对反射和注解了解不多的朋友可以先找一下相关资料了解一下。
关于注解,我在上一篇文章中介绍过
今天的任务呢就是教大家如何一步一步简单的实现一个类似 ButterKnife的依赖注入的效果:
第一步:我们需要自定义注解,如下:
//用于初始化view的
- @Target(ElementType.FIELD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface BindView {
- int value() default 0;
- }
//用于绑定点击事件的- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface BindClick {
- int value() default 0;
- }
从上面的Target里面的值我们可以知道,这两个注解一个是作用于属性,一个是作用于方法的。这里提醒一下,如果如果只有一个参数成员,最好把参数名称设为value,这里可以补一句因为使用该注解时,value作为key可省略,在使用的时候比较方便。第二步:设置注解
- @BindView(R.id.button)
- private Button mButton;
- @BindView(R.id.textview)
- private TextView mTextView;
- @BindClick(R.id.button)
- private void onButtonClick(){
- Toast.makeText(this,"Button被点击了",Toast.LENGTH_SHORT).show();
- }
- @BindClick(R.id.textview)
- private void onTextViewClick(){
- Toast.makeText(this,"TextView被点击了",Toast.LENGTH_SHORT).show();
- }
第三步:获取注解,进行处理- public class InjectUtils {
/** *注入视图 */public static void initView(Activity injectedActivity){ initView(injectedActivity,injectedActivity.getWindow().getDecorView());}/** *注入视图 */public static void initView(YYBaseViewController injectedViewController){ initView(injectedViewController,injectedViewController.getView());}/** *注入视图 */public static void initView(Object injectedSource,View sourceView){ Field[] fields = injectedSource.getClass().getDeclaredFields(); if(isNotNull(fields) && fields.length>0){ for(Field field : fields){ YYInjectView viewInject = field.getAnnotation(YYInjectView.class); if(isNotNull(viewInject)){ int viewId = viewInject.id(); try { field.setAccessible(true); if(field.get(injectedSource)!= null ){ //如果有值就屏蔽,例如float,int等类型 continue; } field.set(injectedSource,sourceView.findViewById(viewId)); }catch (Exception e){ e.printStackTrace(); } } } }}
- public static void inject(final Activity activity) {
-
- Class<Activity> activityClass= (Class<Activity>) activity.getClass();
- Field fields[]=activityClass.getDeclaredFields();
- for(Field field:fields){
- if(field.isAnnotationPresent(BindView.class)){
- int viewId=field.getAnnotation(BindView.class).value();
- View view=activity.findViewById(viewId);
- try {
-
- field.setAccessible(true);
- field.set(activity,view);
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- }
-
- Method methods[]=activityClass.getDeclaredMethods();
- for(final Method method:methods){
- BindClick bindClick=method.getAnnotation(BindClick.class);
- if(bindClick!=null){
- int viewId=bindClick.value();
- activity.findViewById(viewId).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- try {
-
- method.setAccessible(true);
- method.invoke(activity);
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- });
- }
- }
- }
- }
第四步:其实上面已经完成了处理,我们只需要调用一下就可以了,像下面那样:- setContentView(R.layout.activity_main);
-
- InjectUtils.inject(this);
1 0