什么是IOC
官方:控制反转(Inversion of Control,缩写为IoC),是[面向对象编程] 中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
简单理解:就是以前自己需要主动做的事情,变成被动;
不使用ioc的时候:现在你要出门时,需要查看自己手机、口罩、钥匙是否都带了.(主动)
使用ioc的时候:你什么都不需要管,只要一个眼神这些东西都交给你的女朋友去做,自己只需要负责接收就行。(被动)
下面开始介绍如何使用IOC
下面写一个类似 ButterKnife的注解框架
@ContentView(R.layout.activity_main)
public class MainActivity extends BaseAcyivity {
@InjectView(R.id.btn_1)
Button btn1;
@InjectView(R.id.btn_2)
Button btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
Log.e("wwh", btn1.toString());
}
@OnClick({R.id.btn_1, R.id.btn_2})
public void click(View view) {
Toast.makeText(this, "hhd", Toast.LENGTH_LONG).show();
}
@OnLong({R.id.btn_1})
public boolean click111(View view) {
Toast.makeText(this, "111111", Toast.LENGTH_LONG).show();
return false;
}
}
1.通过IOC去加载布局文件
通过ContentView注解得到布局文件的ID
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ContentView {
int value() default -1;
}
2.加载布局
//反射执行setContentView()方法
/**
* 注入布局
*
* @param context
*/
private static void injectLayout(Object context) {
int layoutId = 0;
Class<?> clzz = context.getClass();
ContentView contentView = clzz.getAnnotation(ContentView.class);
if (contentView != null) {
layoutId = contentView.value();
//反射执行setContentView()方法
try {
Method setContentView = context.getClass().getMethod("setContentView", int.class);
setContentView.invoke(context, layoutId);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
3.控件注入
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectView {
int value() default -1;
}
/**
* 注入控件
*
* @param context
*/
private static void injectView(Object context) {
Class<?> clzz = context.getClass();
Field[] declaredFields = clzz.getDeclaredFields();//获取所有定义的变量
for (Field declaredField : declaredFields) {
InjectView injectView = declaredField.getAnnotation(InjectView.class);
if (injectView != null) {
int viewId = injectView.value();
try {
//反射执行findViewById()
Method findViewById = clzz.getMethod("findViewById", int.class);
View view = (View) findViewById.invoke(context, viewId);
declaredField.setAccessible(true);
declaredField.set(context, view);//context.field=view
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}