反射和注解在android开发中的应用

一,反射:说白了反射主要解决那些我们平时解决不了的问题。比如一个类的构造,属性,普通方法为私有的情况下,或者某些方法虽然不是私有的方法但是是被隐藏的方法,我们就需要使用反射才能获得他们。一般使用Class类来完成反射,这个类把成员变量划分为Filed区域,把构造划分在Construct,把普通方法划分在method区域。下面就来看反射的应用。

1,通过反射获得构造方法

1.1 通过反射获得构造为空的构造方法:

首先定义一个TestBean类,testBean的构造方法是私有我空


public class TestBean {
    private String name;
    private TestBean(){
    }


    public String getName() {
        return name;
    }

    public void systemInfo(){
        Log.e("TAG","无参构造");
    }
}

MainActivity的onCreate()方法中这样写:

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

        try {
            //newInstance()方法是基于无参构造调用的,所以需要被反射调用的类中必须要有无参构造
            TestBean testBean=TestBean.class.newInstance();
            testBean.systemInfo();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

1.2通过反射获得构造不为空的构造方法:

首先定义一个TestBean类,testBean的构造方法是私有不为空


public class TestBean {
    private String name;
    private TestBean(String name){
        this.name=name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void systemInfo(){
        Log.e("TAG",this.name);
    }
}

MainActivity的onCreate()方法中这样写:

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

        //这种是带构造参数的
        try {
            //如果有两个参数,第二个参数是int型的,那么第二个参数就应该写成int.class
            Constructor<TestBean> constructor= TestBean.class.getDeclaredConstructor(String.class);
            constructor.setAccessible(true);//设置权限
            //如果有两个参数第二个参数是int型的,那么第二个参数在这里直接写数字
            TestBean testBean=constructor.newInstance("yaoliangyong");//调用构造方法传参数
            testBean.systemInfo();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

输出结果是:

2019-06-18 14:26:29.959 22982-22982/com.example.didi.myproject E/TAG: yaoliangyong

2,通过反射获取私有的方法

定义一个类,这个类中有一个私有的方法

扫描二维码关注公众号,回复: 8495746 查看本文章
import android.util.Log;

public class TestBean {
    private String name;

    public TestBean(String name){
        this.name=name;
    }


    public String getName() {
        return name;
    }

    private void systemInfo(){
        Log.e("TAG","私有方法");
    }
}

MainActivity中的写法:

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

        //这种是带构造参数的
        try {
            //newInstance()方法是基于无参构造调用的,所以需要被反射调用的类中必须要有无参构造
            TestBean testBean=new TestBean("yaoliangyogn1");
            //因为systemInfo()方法没有参数可以这样写,如果一个方法有参数(假设为String)的话就要写成
            //Method method=TestBean.class.getDeclaredMethod("systemInfo",String.class);
            Method method=TestBean.class.getDeclaredMethod("systemInfo");
            //这句话是说谁去执行它
            method.setAccessible(true);
            method.invoke(testBean);
            //这是有参数的使用用的
            //method.invoke(testBean,"zhenxin1");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

输出结果:

2019-06-18 15:28:06.017 28957-28957/? E/TAG: 私有方法

3,通过反射获取属性:

首先定义一个类


public class TestBean {
    private String name="真心英雄";

    public TestBean(){
    }


    public String getName() {
        return name;
    }

}

MainActivity中的写法:

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

        //这种是带构造参数的
        try {
            //newInstance()方法是基于无参构造调用的,所以需要被反射调用的类中必须要有无参构造
            TestBean testBean=new TestBean();
            Field field= testBean.getClass().getDeclaredField("name");
            field.setAccessible(true);
            String name= (String) field.get(testBean);
            Log.e("TAG",name);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

二,注解

注解知识一个标识,下面是注解的基本使用方法

1,创建一个ViewById接口


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)//这表示放在属性上面
@Retention(RetentionPolicy.RUNTIME)//这表示运行时起作用,也就是App已经起来了
//@Retention(RetentionPolicy.CLASS)这表示编译时,代表点了上面的三角按钮起作用
public @interface ViewById {
    int value();//这表示只能放一个参数,如果想放两个参数的话可以使用int[] value();
    //若果想放一个String类型的参数,可以使用
    //String name="";
}

2,在MAinActivity中这样使用:
 


import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.widget.TextView;

public class MainActivity extends Activity {

    @ViewById(R.id.text_view)
    private TextView textView;

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

        textView.setText("textView");


    }
}

当然,这样肯定还是编译不过的,但是大致使用是这样的,具体使用方法请看下面的讲解:

首先新建一个注解接口ViewById

mport java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)//这表示放在属性上面
@Retention(RetentionPolicy.RUNTIME)//这表示运行时起作用,也就是App已经起来了
//@Retention(RetentionPolicy.CLASS)这表示编译时,代表点了上面的三角按钮起作用
public @interface ViewById {
    int value();//这表示只能放一个参数,如果想放两个参数的话可以使用int[] value();
    //若果想放一个String类型的参数,可以使用
    //String name="";
}

接着新建一个类


import android.app.Activity;
import android.view.View;

import java.lang.reflect.Field;

//所有的注解还是需要用代码实现的,不可能用了注解之后就不使用findViewById()了
public class ViewUtils {
    public static void inject(Activity activity){
        //1,找到MainActivity中的所有属性
        Field[] fields=activity.getClass().getDeclaredFields();//这就获取到了所有属性,也包括viewPager,当然我们并不关心viewPager属性
        //2,过滤关于ViewById属性(之所以过滤是因为不能任何属性都需要注解)
        //一般使用for循环过滤
        for (Field field:fields){
            ViewById viewById=field.getAnnotation(ViewById.class);
            if (viewById!=null){
                //3,findVieById肯定是不能少
                View view=activity.findViewById(viewById.value());
                //4,反射注入(把找到的属性注入)
                field.setAccessible(true);
                try {
                    //第一个参数代表属性所在类,第二个属性代表属性值
                    field.set(activity,view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

在MAinActivity中的写法:


import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.widget.TextView;

public class MainActivity extends Activity{

    @ViewById(R.id.text_view)
    private TextView textView;

    int viewPager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewUtils.inject(this);
        textView.setText("textView");


    }
}
发布了75 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/yaoyaoyao_123/article/details/92786137