什么是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 {
public void callback(String method);
public void callback(String method, Class<?> dataClassType, Object 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; }
protected void callback(int result, Object data) { mModuleListener.callback(result, data); }
@Deprecated protected void callback(String method) { mModuleListener.callback(method); }
@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); } }
public void changeModule(AbsModule module) { module.setModuleListener(this); }
@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(); } } }
@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(); } } }
@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<>();
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; }
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; }
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; }
protected abstract void dataCallback(int result, Object data); }
|
总结
到现在为止,框架核心部分已经完成了,现在让我们整理下整个框架到底是怎样运作的!
老规矩,还是用图来说明,没什么比图更让人易懂的。
下图是整个框架的流程图:
图不难懂,我就不废话了,我直接给出例子就行了,大家都是码农,我相信没几个码农喜欢看文字的,都喜欢看代码直接干的。。
例子
Module1
import android.content.Context;
import com.example.yuyu.blogframedemo.frame.AbsModule;
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;
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;
public class MainActivity extends AbsActivity{
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }
private void myCallback(String data){ show(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(); } }
|