开始之前
反射,一直是我的一块心病,必须啃下来。
在研究插件化,在插件内部启动插件自身的组件,如:Activity ,Service , BroadcastReceiver等等。由于在插件内部没有上下文环境是无法启动组件的,必须依赖宿主的代理组件来代理
插件组件。而通过代理组件间接执行插件中组件的OnCreate, OnStartCommand , onReceive
方法,而执行这些方法都需要使用反射来获取类对象
,进而执行方法。
如下代码中,在代理 ProxyActivity中,通过反射拿到插件Activity,进而执行onCreate方法
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "onCreate: ");
String className = getIntent().getStringExtra(Constants.CLASS_NAME);
//真正的加载 插件里面的Activity
// 动态获取className , 不能写死(包名+类名)
// String className = null;
try {
// 拿到插件包中的第一个Activity
// 由于插件是直接以APK文件存在于sd卡,并没有加载过,所以需要类加载器加载
Class pluginClass = getClassLoader().loadClass(className);
// 实例化插件包中的Activity
Constructor constructor = pluginClass.getConstructor(new Class[]{});
Object pluginActivity = constructor.newInstance(new Object[]{});
// 强转为ActivityInterface
activityInterface = (ActivityInterface) pluginActivity;
// 将宿主的环境注入给插件
activityInterface.insertAppActivity(this);
// 执行插件onCreate 方法
// 可以从宿主 携带参数 给 插件
Bundle bundle = new Bundle();
bundle.putString("fromAppInfo", "我是来自宿主的一条信息");
// 间接调用pluginActivity的onCreate方法
activityInterface.onCreate(bundle);
} catch (Exception e) {
e.printStackTrace();
}
}
通过反射构建对象
测试类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private void introduce(String name, int age) {
System.out.println(String.format("introduce 自我介绍: 我是 %s , 正少年 %d", name, age));
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
1. 类的构造方法无参数
如果拿不到类的全限定名(包名+类名),可以通过以下方式反射构建,
@Test
public void reflectTest2() {
try {
Person personObj = (Person) Class.forName("com.purang.stander.reflect.Person").newInstance();
System.out.println(personObj.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
com.purang.stander.reflect.Person@722c41f4
如能拿到全限定名(包名+类名),可以通过
@Test
public void reflectTest3() {
try {
Person person1 = Person.class.newInstance();
System.out.println(person1.toString());
Person person2 = person1.getClass().newInstance();
System.out.println(person2);
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
com.purang.stander.reflect.Person@722c41f4
com.purang.stander.reflect.Person@5b80350b
2. 类的构造方法有参数
@Test
public void reflectTest4() {
Class[] classes = {String.class, int.class};
try {
// @param parameterTypes :the parameter array
// @param initargs 构造对象的参数
Person person = (Person) Class.forName("com.purang.stander.reflect.Person").getConstructor(classes).newInstance("城南一霸贾十七", 18);
System.out.println(person.toString());
} catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException | ClassNotFoundException e) {
e.printStackTrace();
}
}
通过forName加载到类的加载器,
输出:
Person{name='城南一霸贾十七', age=18}
反射获取类方法,并执行
@Test
public void reflectTest5() {
Class[] classes = {String.class, int.class};
try {
Person person = (Person) Class.forName("com.purang.stander.reflect.Person").newInstance();
/**
* getMethod() , getMethods() / getFields() , getField() 只能获取public 修饰的方法和属性
* getDeclaredMethod() , getDeclaredMethods() / getDeclaredField(), getDeclaredFields() 可以获取私有方法和属性
*/
Method introduceMethod = person.getClass().getDeclaredMethod("introduce", classes);
introduceMethod.setAccessible(true);
introduceMethod.invoke(person, "城南一霸贾十七", 18);
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
introduce 自我介绍: 我是 城南一霸贾十七 , 正少年 18