Android中通过注解代替findViewById方法

尊重原创 http://write.blog.csdn.net/postedit/26507351

这篇文章主要讲解注解实现findViewById的功能,首先我们来熟悉一下在java中怎么定义一个注解和解析一个注解

注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:Override,Deprecated,SuppressWarnings

Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法

Deprecated表示在新版本的 jdk中已经不建议使用这个方法或者属性

SuppressWarning就是屏蔽掉一些警告

知道了注解的概念后,我们就来自定义注解

注解的定义和接口的接口非常像,在interface的前面多了一个@

public @interface TestPerson
{

}

千万不能把前面的@符号弄掉了,弄掉了就成了接口的定义了,上面是一个最简单注解的定义,当然注解和类一样,也可以定义属性,如下:

public @interface TestPerson
{
  //name既是这个注解的属性,也是注解的方法,调用name()返回值就是name
  String name() default "gavin";
}

我现在想定义两个注解,一个注解用来说明某个类的意义,另一个注解用来说明类中的某个方法由谁测试的,便于追究责任,定义如下:

//用来标注某个类是用来干嘛的
public @interface ClassFunction
{
  String value() default "";
}

//用来标注类中的方法是被谁测试的
public @interface TestPerson
{
  //name是属性而不是方法,gavin是它的默认值,在定义的时候可以不用给定默认值
  String name() default "gavin";
}

那么怎么限定一个注解是用在类上还是用在方法上?比如Override就是用在方法上的注解,Deprecated是既可以用在方法上面,也可以用在类上面,我们直接看看Override是怎么实现的吧

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

我们发现这两个注解在定义的过程中都使用了其他的注解,像Target和Retention这种注解叫做元注解,我们分别看看它们的意思吧

Target注解的功能就是表明你这个注解是用在什么地方的,它的值是一个枚举型

  1.CONSTRUCTOR:用于描述构造器

    2.FIELD:用于描述域

    3.LOCAL_VARIABLE:用于描述局部变量

    4.METHOD:用于描述方法

    5.PACKAGE:用于描述包

    6.PARAMETER:用于描述参数

    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

Retention注解的功能差不多说明的就是你的注解的生命周期吧,就是什么时候失效,它的值如下

1.SOURCE:在源文件中有效(即源文件保留)

    2.CLASS:在class文件中有效(即class保留)

    3.RUNTIME:在运行时有效(即运行时保留)

我就介绍这两个元注解吧,其他的感觉也用的不是很多,如果你感兴趣可以自己Google一下

那么我们就完善我们自己的注解吧

@Target(ElementType.METHOD)//作用于方法
@Retention(RetentionPolicy.RUNTIME)//在运行时有效(即运行时保留)
public @interface TestPerson
{
  //name是属性而不是方法,gavin是它的默认值,在定义的时候可以不用给定默认值
  String name() default "gavin";
}

@Target(ElementType.TYPE)//作用于类上
@Retention(RetentionPolicy.RUNTIME)//在运行时有效(即运行时保留)
public @interface ClassFunction
{
  String value() default "";
}

那么我们就来使用一下我们的注解吧

@ClassFunction("用于描述一个人的基本信息")
public class Person
{
  private static final String TAG = "Person";

  @TestPerson(name="jj")
  public void setName()
  {

  }
}

这里要说明一点就是:如果某个注解属性使用value作为名称如ClassFunction中的value,那么赋值的时候可以直接@ClassFunction("用于描述一个人的基本信息"),但是如果你使用的是其他名称,那么必须@TestPerson(name="jj")这样调用

以上就是定义一个注解的过程,下面我们来解析一个注解

定义一个TestPerson注解

/**
 * com.annotation.TestPerson
 * @author yuanzeyao <br/>
 * create at 2014年5月21日 下午1:30:14
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestPerson {

  String name();
}

然后再Person类中加入注解

public class Person {
  private static final String TAG = "Person";
  @TestPerson(name="gavin")
  public void getName()
  {

  }
}

解析注解

public class Main {
  private static final String TAG = "Main";
  public static void main(String[] args)
  {
     Person person=new Person();
	 //获得Person对应的Class
     Class<Person> clazz=Person.class;
     try {
	  //找到getName方法
      Method method=clazz.getMethod("getName",null);
	  //判断是否被TestPerson标注
      if(method.isAnnotationPresent(TestPerson.class))
      {
		//调用getName方法
        method.invoke(person, null);
		//得到TestPerson注解的实例
        TestPerson test=method.getAnnotation(TestPerson.class);
		//获得其name属性
        String name=test.name();
        System.out.println("this method is test by-->"+name);
      }
    } catch (SecurityException e) {
    } catch (NoSuchMethodException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    } catch (InvocationTargetException e) {
    }
  }
}

已经将定义注解和解析注解讲解完了,下面来具体分析一下怎么在Android中使用注解来代替findViewById

定义一个注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectView
{
  //id就是控件id,在某一个控件上使用注解标注其id
  int id() default -1;
}

在Activity中加入注解

public class MainActivity extends Activity
{
  public static final String TAG="MainActivity";
  //标注TextView的id
  @InjectView(id=R.id.tv_img)
  private TextView mText;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
      autoInjectAllField(this);
    } catch (IllegalAccessException e) {
    } catch (IllegalArgumentException e) {
    }

    if(mText!=null)
      mText.setText("Hello Gavin");
  }

  public void autoInjectAllField(Activity activity) throws IllegalAccessException, IllegalArgumentException
  {
	//得到Activity对应的Class
    Class clazz=this.getClass();
	//得到该Activity的所有字段
    Field []fields=clazz.getDeclaredFields();
    Log.v(TAG, "fields size-->"+fields.length);
    for(Field field :fields)
    {
	  //判断字段是否标注InjectView
      if(field.isAnnotationPresent(InjectView.class))
      {
        Log.v(TAG, "is injectView");
		//如果标注了,就获得它的id
        InjectView inject=field.getAnnotation(InjectView.class);
        int id=inject.id();
        Log.v(TAG, "id--->"+id);
        if(id>0)
        {
		  //反射访问私有成员,必须加上这句
          field.setAccessible(true);
		  //然后对这个属性复制
          field.set(activity, activity.findViewById(id));
        }
      }
    }
  }

}

好了,就写到这里吧,欢迎留言讨论

Android中通过注解代替findViewById方法,布布扣,bubuko.com

时间: 2024-10-02 09:55:44

Android中通过注解代替findViewById方法的相关文章

理解Android中的注解与反射

前言 最近一段时间在研究EventBus和Retrofit 的过程中,都遇到了注解这个概念.由于在学习Java的时候对这方面没有深入了解过,所以看起相关的代码来,总会有点不知其所以然,这里就注解和反射的使用做一下总结. 这里我们先从反射说起,了解了反射的意义及用法后,我们在看看注解的使用,最后叙述一下在Android开发中是怎样结合使用注解与反射. 反射 Java反射(Reflection)定义 Java反射机制是指在运行状态中 对于任意一个类,都能知道这个类的所有属性和方法: 对于任何一个对象

Android 中使用自定义字体的方法

1.Android系统默认支持三种字体,分别为:“sans”, “serif”, “monospace 2.在Android中可以引入其他字体 . <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:Android="http://schemas.android.com/apk/res/android" Android:layout_width="fill

Android中加载位图的方法

Android中加载位图的关键的代码: AssetManager assets =context.getAssets(); //用一个AssetManager 对象来从应用程序包的已编译资源中为工程加载资产 InputStream istream=assets.open("/*位图的名字*/"); BitmapFactory.Options options=new BitmapFactory.Options(); options.inPreferredConfig =Bitmap.Co

Android中播放Gif图片的方法

Android中播放Gif图片的方法. 主要原理是取出Gif中的每一帧图片,分别设置到ImageView上边展示出来 使用到Code.Google上边的一个开源类库GifDecoder,下载不了的可以从我后边给出的Demo中搬运. 准备一个类继承自ImageView重写其构造方法同时传入一个输入流. [java] view plaincopyprint? <span style="font-size:18px;">public class GifDecoderView ex

Android中集成第三方库的方法和问题

声明: 1. 本文参考了网上同学们的现有成果,在此表示感谢,参考资料在文后有链接. 2. 本文的重点在第三部分,是在开发中遇到的问题及解决办法.第一,第二部分为参考网上同学们的成果加以整理而成. 3. 欢迎转载,交流,请尊重作者劳动成果:转载请注明出处,谢谢! Android中使用第三方库可能有两种:Java库.jar和原生库.so/.a,如果只是做上层APK开发,这两种库都可以通过Eclipse集成开发环境进行集成,如果是平台级开发,则都可通过源码集成.本文整理这两种集成方式使用步骤,以下假设

Android中关联源码的方法

这里给大家介绍一个很方便的关联源码的方法. 1.打开Android SDK Manager.把你所使用的版本的API给下载下来,如下图所示... 2.关联源码时,将源码关联到对应API的目录,如: E:\开发者工具\android可能工具包\adt-bundle-windows-x86-20130729\sdk\sources\android-18 这时候,就能关联成功了... Android中关联源码的方法

android中获取root权限的方法以及原理(转)

一. 概述 本文介绍了android中获取root权限的方法以及原理,让大家对android 玩家中常说的“越狱”有一个更深层次的认识. 二. Root 的介绍 1. Root 的目的 可以让我们拥有掌控手机系统的权限,比如删除一些system/app下面的无用软件,更换开关机铃声和动画,拦截状态栏弹出的广告等. 2. Root的原理介绍 谷歌的android系统管理员用户就叫做root,该帐户拥有整个系统至高无上的权利,它可以访问和修改你手机几乎所有的文件,只有root才具备最高级别的管理权限

Android中常用的bitmap处理方法

收集了很多bitmap相关的处理方法,几乎全部应用在项目中,所以特记录下! package com.tmacsky.utils; import java.io.ByteArrayOutputStream; import java.io.IOException; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.gr

Android中ViewMapping注解

1.Java.lang包中常用的注解有@Override,@Deprected(已经废弃),@SupressWarning(屏蔽掉一些警告.)我们可以自定义注解. 2.Java注解之@Retention,@Documented,@Inherited. Retention注解,保留注解说明,这种类型的猪儿会被保留到哪个阶段,有三个值:RetentionPolicy.SOURCE(只有源码级别保留,编译时被忽略),RetentionPolicy.CLASS(class文件中保留,Jvm被忽略),Re