写在前面
这篇文章是我以前写在CSDN上的,由于感觉CSDN上写作体验感觉不好,现在准备把以前的一些文章转到简书
以上都是废话。。。。。
什么是IOC?
IOC框架称为控制控制反转框架也称为依赖注入框架,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。
IOC相关概念
在写一个框架之前,我们需要了解下IOC的相关概念。
简单来说,对象和IOC容器的关系就像电脑和外设之间的关系,其中电脑相当于对象,而IOC容器相当于一个个不同的电脑外设。外设具有不同的功能,并且他们和电脑之间都遵循着某种协议(如USB2.0协议),因此它们在彼此独立的同时却又能相互联系。
输入功能原本属于电脑的,但是外设键盘却能通过电脑提供的相关接口来控制电脑的输入功能,这就是IOC概念里面的控制反转。由于电脑和外设间都遵循着USB协议,键盘便可以实现随意切换,却不影响键盘的输入功能,这就是IOC概念里面的依赖注入。
好了,了解完IOC协议后,便可以开始绘制相应的架构图了。
IOC框架图
这是我用StartUml绘制的UML图。
如这个图所示,整个IOC框架可以分为5个部分
1、ModuleListener,IOC的核心接口,相当于电脑的USB协议
2、AbsModule,这就是IOC容器,IOC容器功能都在这个类里面实现
3、IOCProxy,对象的静态代理,相当于电脑的USB接口
4、ModuleFactory,IOC容器的享元工厂,用于创建IOC容器
5、AbsActivity,具体的对象
有了概念,有了图纸,现在终于可以愉快的码代码了
功能实现
ModuleListener
如上文所说的那样,ModuleListener是整个IOC框架的IOC协议,它本质上就是一个接口,定义了几个方法,仅此而已,是的,所谓的IOC协议就是那么简单。
代码如下:
public interface ModuleListener {
/**
* 无参的回调
*
* @param method 方法名
*/
public void callback(String method);
/**
* 带参数的回调
*
* @param method 方法名
* @param dataClassType 参数类型
* @param data 数据
*/
public void callback(String method, Class<?> dataClassType, Object data);
/**
* 统一接口的回调,回调接口为dataCallback
*
* @param result 返回码
* @param data 回调数据
*/
public void callback(int result, Object data);
}
AbsModule
AbsModule,这就是IOC框架的IOC容器,IOC容器的功能都应该在它的子类里面实现。
AbsModule依赖于ModuleListener接口,它持有ModuleListener的引用。其实说白了它就是一个观察者对象,仅此而已....
代码如下:
public class AbsModule {
public String TAG = "";
private Context mContext;
private ModuleListener mModuleListener;
public AbsModule(Context context) {
mContext = context;
init();
}
/**
* 初始化一些东西
*/
private void init() {
String className = getClass().getName();
String arrays[] = className.split("\\.");
TAG = arrays[arrays.length - 1];
}
public void setModuleListener(ModuleListener moduleListener) {
if (moduleListener == null)
throw new NullPointerException("ModuleListener为空");
this.mModuleListener = moduleListener;
}
public Context getContext() {
return mContext;
}
/**
* 统一的回调
*
* @param result 返回码
* @param data 回调数据
*/
protected void callback(int result, Object data) {
mModuleListener.callback(result, data);
}
/**
* module回调
*
* @param method 回调的方法名
*/
@Deprecated
protected void callback(String method) {
mModuleListener.callback(method);
}
/**
* 带参数的module回调
*
* @param method 回调的方法名
* @param dataClassType 回调数据类型
* @param data 回调数据
*/
@Deprecated
protected void callback(String method, Class<?> dataClassType, Object data) {
mModuleListener.callback(method, dataClassType, data);
}
}
IOCProxy
类如其名,IOCProxy本身就是一个静态代理,代理本身其实很简单,说白了,代理就是我们平时所说的“黑中介”,在这里,我们的代理仅仅只实现了两个功能:
1、给IOC对象设置观察者,这个观察者是继承于AbsModule的子类。
2、中转AbsModule回调的数据,将数据再次回调到AbsActivity的相应接口。
代码如下:
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IOCProxy implements ModuleListener {
private static final String TAG = "IOCProxy";
private static final String mMethod = "dataCallback";
private Object mObj;
/**
* 初始化静态代理
*/
public static IOCProxy newInstance(Object obj, AbsModule module) {
return new IOCProxy(obj, module);
}
/**
* 被代理对象
*/
private IOCProxy(Object obj, AbsModule module) {
this.mObj = obj;
if (module != null) {
module.setModuleListener(this);
}
}
/**
* 动态切换不同的观察者
* @param module
*/
public void changeModule(AbsModule module) {
module.setModuleListener(this);
}
/**
* 统一的数据回调
*
* @param result 返回码
* @param data 回调数据
*/
@Override
public void callback(int result, Object data) {
synchronized (this) {
try {
Method m = mObj.getClass().getDeclaredMethod(mMethod, int.class, Object.class);
m.setAccessible(true);
m.invoke(mObj, result, data);
} catch (NoSuchMethodException e) {
Log.e(TAG, "无法找到" + mMethod + "方法");
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 数据回调
*
* @param method 方法名
*/
@Override
@Deprecated
public void callback(String method) {
synchronized (this) {
try {
Method m = mObj.getClass().getDeclaredMethod(method);
m.setAccessible(true);
m.invoke(mObj);
} catch (NoSuchMethodException e) {
Log.e(TAG, "无法找到" + method + "方法");
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 带参数的回调
*
* @param method 方法名
* @param dataClassType 参数类型,如 int.class
* @param data 数据
*/
@Override
@Deprecated
public void callback(String method, Class<?> dataClassType, Object data) {
synchronized (this) {
try {
Method m = mObj.getClass().getDeclaredMethod(method, dataClassType);
m.setAccessible(true);
m.invoke(mObj, data);
} catch (NoSuchMethodException e) {
Log.e(TAG, "无法找到" + method + "方法");
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
在这个类里,博主根据以前的需求写了几种不同的代理回调。
但是,我强烈建议你使用带有返回码的统一回调接口,该方法规定了AbsActivity的回调函数,实现了数据流的统一,一致性总归是好的,便于我们后期维护。
ModuleFactory
ModuleFactory是一个享元工厂,IOC容器的构建都是由它来完成了,享元实现不同对象的容器之间的共享。
代码如下:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class ModuleFactory {
private static final String TAG = "ModuleFactory";
private static Map<String, AbsModule> mModules = new HashMap<>();
/**
* 获取Module
*/
protected static <T extends AbsModule> T getModule(Context context, Class<T> clazz) {
T module = (T) mModules.get(String.valueOf(clazz.hashCode()));
if (module == null) {
return newInstanceModule(context, clazz);
}
return module;
}
/**
* 构造一个新的Module
*/
private static <T extends AbsModule> T newInstanceModule(Context context, Class<T> clazz) {
Class[] paramTypes = {Context.class};
Object[] params = {context};
try {
Constructor<T> con = clazz.getConstructor(paramTypes);
T module = con.newInstance(params);
mModules.put(String.valueOf(clazz.hashCode()), module);
return module;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
AbsActivity
写了这么久,终于快到尾声了...
AbsActivity是IOC框架的对象,Activity也没啥好说的,大家都懂的,直接放代码:
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public abstract class AbsActivity extends AppCompatActivity {
private static IOCProxy mProxy;
private IOCProxy mNewProxy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNewProxy = IOCProxy.newInstance(this, null);
}
/**
* 利用反射来对代理进行重指向
*/
private void setProxy() {
mProxy = mNewProxy;
}
/**
* 获取Module
*/
protected static <T extends AbsModule> T getModule(AbsActivity activity, Class<T> clazz) {
Method m = ReflectionUtil.getMethod(activity.getClass(), "setProxy", new Class[]{});
try {
m.invoke(activity);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
T module = ModuleFactory.getModule(activity, clazz);
mProxy.changeModule(module);
return module;
}
/**
* 统一的回调接口
*
* @param result 返回码,用来判断是哪个接口进行回调
* @param data 回调数据
*/
protected abstract void dataCallback(int result, Object data);
}
总结
到现在为止,框架核心部分已经完成了,现在让我们整理下整个框架到底是怎样运作的!
老规矩,还是用图来说明,没什么比图更让人易懂的。
下图是整个框架的流程图:
图不难懂,我就不废话了,我直接给出例子就行了,大家都是码农,我相信没几个码农喜欢看文字的,都喜欢看代码直接干的。。
例子
Module1
import android.content.Context;
import com.example.yuyu.blogframedemo.frame.AbsModule;
/**
* Created by yuyu on 2015/9/6.
*/
public class Module1 extends AbsModule{
public Module1(Context context) {
super(context);
}
public void module1Test(){
callback(100, "我是Module1111111");
}
public void cusomCallback(){
callback("myCallback", String.class, "我是Module11的自定义回调......");
}
}
Module2
import android.content.Context;
import com.example.yuyu.blogframedemo.frame.AbsModule;
/**
* Created by yuyu on 2015/9/6.
*/
public class Module2 extends AbsModule{
public Module2(Context context) {
super(context);
}
public void module2Test(){
callback(101, "我是Module22222222");
}
}
MainActivity
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.yuyu.blogframedemo.R;
import com.example.yuyu.blogframedemo.frame.AbsActivity;
/**
* Created by yuyu on 2015/9/6.
*/
public class MainActivity extends AbsActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 回调到自定义的方法
* @param data
*/
private void myCallback(String data){
show(data);
}
/**
* 数据回调,当然你也可以回调到指定的方法里面
* @param result 返回码,用来判断是哪个接口进行回调
* @param data 回调数据
*/
@Override
protected void dataCallback(int result, Object data) {
show(String.valueOf(data));
}
public void onClick(View view){
switch (view.getId()){
case R.id.module1:
getModule(this, Module1.class).module1Test();
break;
case R.id.module2:
getModule(this, Module2.class).module2Test();
break;
case R.id.custom_module:
getModule(this, Module1.class).cusomCallback();
break;
}
}
private void show(String msg){
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
}
网友评论