Androi中IOC(控制反转)理解

   这仅是本人的学习笔记:

           我们先看,IOC是什么,干什么用的?控制反转(Inversion of Control),一种设计模式,spring框架的核心。目的:降低耦合性。

        IoC的原则是:一个类,需要成员变量,new出来,NO,我们不要new,这样耦合度太高;你配置个xml文件,里面标明哪个类,里面用了哪些成员变量,等待加载这个类的时候,我  帮你注入(new)进去;

           实例:通过IOC模式可以彻底解决接口驱动产生的耦合性。

           接口驱动产生的耦合:接口一定需要实现,实现不同,以来不同,耦合就产生了。

           IOC解决方案:把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中(工厂模式的升华)。

    

  为了实现调用者和被调用者解耦,分离,一般是通过工厂模式实现的,下面将通过比较工厂模式和Ioc模式不同,加深理解Ioc模式。

  假设有两个类B 和 C:B作为调用者,C是被调用者。一般的做法是:

public class B{
   private C comp=new C(); 
  ......
    }
     工厂模式实现如下:
public class B{
  private C comp; 
  private final static MyFactory myFactory = MyFactory.getInstance();

  public B(){
    this.comp = myFactory.createInstanceOfC();

  }
   public void someMethod(){
    this.comp.sayHello();
  } 
}

 使用Ioc依赖性注射实现Picocontainer如下:

public class B{
  private C comp; 
  public B(C comp){
    this.comp = comp;
   }
   public void someMethod(){
    this.comp.sayHello();
   }
}
//外部容器实现,控制程序间的关系。CImp类为C接口/类的一个具体实现。

public class client{
   public static void main( String[] args ) {
    DefaultPicoContainer container = new DefaultPicoContainer();
    container.registerComponentImplementation(CImp.class); //向B类实现注射C类具体实现
    container.registerComponentImplementation(B.class);
    B b = (B) container.getComponentInstance(B.class);
    b.someMethod();
   }
}

http://www.cnblogs.com/devinzhang/archive/2012/01/27/2330098.html

     和工厂模式的区别:把IoC看作是一个大工厂,只不过这个大工厂里要生成的对象都是在XML文件中给出定义的,然后利用Java 的“反射”编程,根据XML中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由XML文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

主要区别体现在B类的代码,如果使用Ioc,在B类代码中将不需要嵌入任何工厂模式等的代码,因为这些工厂模式其实还是与C有些间接的联系,这样,使用Ioc彻底解耦了B和C之间的联系。使用Ioc带来的代价是:需要在客户端或其它某处进行B和C之间联系的组装。

    优点:因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拔(有点象USB接口和SCSI硬盘了)。

   缺点:(1)生成一个对象的步骤变复杂了(事实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3)缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。

http://baike.baidu.com/view/1486379.htm?from_id=4853&type=syn&fromtitle=ioc&fr=aladdin

举例:齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似。

可以把IOC比喻成“粘合剂”

控制反转由来:对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来

解依赖注入的过程:生活举例:电脑,我,u盘(或者移动硬盘)  电脑不决定usb接口挂载什么设备,有“我”来决定挂载那种设备。”我“=IOC容器

好处:1,一个坏了,不影响另一个———>可维护性比较好

           2,usb厂商,电脑厂商————>分工明确  

           3,usb可以插在DV上————>复用性好

           4,把对象生成放在配置文件里定义,若更换子类,只需修改配置文件————>热插拔性

http://blog.csdn.net/wanghao72214/article/details/3969594

         项目分层开发问题,分为控制层、业务层、DAO层等。然后每一层要一个包放接口,一个包放实现呢?只要一个实现包不行么~刚好,如果你了解了IoC,你就知道这些个接口的作用了,上面不是说,你不用new,你只要声明了成员变量+写个配置文件,有人帮你new;此时,你在类中,就可以把需要使用到的成员变量都声明成接口,然后你会发现,当实现类发生变化的时候,或者切换实现类,你需要做什么呢?你只要在配置文件里面做个简单的修改。如果你用的就是实实在在的实现类,现在换实现类,你需要找到所有声明这个实现类的地方,手动修改类名;

    写个配置文件,多麻烦——>注解 例如@Inject  (怎么注入:其实就是把字符串类路径变成类)

     终于进入正题了:Android IOC框架

       就是帮大家注入所有的控件,布局文件,监听事件等(xUtils,afinal)

       目标举例:

@ContentView(value = R.layout.activity_main)
   public class MainActivity extends BaseActivity
   {
	@ViewInject(R.id.id_btn)
	private Button mBtn1;
	@ViewInject(R.id.id_btn02)
	private Button mBtn2;
     以xUtils举例:

  

/**
	 * 注入主布局文件
	 * 
	 * @param activity
	 */
	private static void injectContentView(Activity activity)
	{
		Class<? extends Activity> clazz = activity.getClass();
		// 查询类上是否存在ContentView注解
		ContentView contentView = clazz.getAnnotation(ContentView.class);
		if (contentView != null)// 存在
		{
			int contentViewLayoutId = contentView.value();
			try
			{
				Method method = clazz.getMethod(METHOD_SET_CONTENTVIEW,
						int.class);
				method.setAccessible(true);
				method.invoke(activity, contentViewLayoutId);
			} catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}

备注:有个常量:

  1. private static final String METHOD_SET_CONTENTVIEW = "setContentView";  
private static final String METHOD_FIND_VIEW_BY_ID = "findViewById";
	/**
	 * 注入所有的控件
	 * 
	 * @param activity
	 */
	private static void injectViews(Activity activity)
	{
		Class<? extends Activity> clazz = activity.getClass();
		Field[] fields = clazz.getDeclaredFields();
		// 遍历所有成员变量
		for (Field field : fields)
		{
			
			ViewInject viewInjectAnnotation = field
					.getAnnotation(ViewInject.class);
			if (viewInjectAnnotation != null)
			{
				int viewId = viewInjectAnnotation.value();
				if (viewId != -1)
				{
					Log.e("TAG", viewId+"");
					// 初始化View
					try
					{
						Method method = clazz.getMethod(METHOD_FIND_VIEW_BY_ID,
								int.class);
						Object resView = method.invoke(activity, viewId);
						field.setAccessible(true);
						field.set(activity, resView);
					} catch (Exception e)
					{
						e.printStackTrace();
					}

				}
			}

		}

	}
获取声明的所有的属性,遍历,找到存在ViewInject注解的属性,或者其value,然后去调用findViewById方法,最后把值设置给field~~~

public static void inject(Activity activity)
	{
		
		injectContentView(activity);
		injectViews(activity);
		
	}


     

补充:

1.成为Android高手一般分为六个阶段:

        第一阶段:熟练掌握Java SE,尤其是对其内部类、线程、并发、网络编程等需要深入研究;熟练掌握基于HTTP协议的编程,清楚POST和GET等请求方式流程和细节;能够进行基本的Java Web编程,如果能够使用Java EE则更好;

        第二阶段:精通Android的核心API的使用,例如四大组件所涉及的API、Context等,精通核心界面的编程,例如ListView的编程;到达这个阶段已经能够做大部分基本的应用开发了;

        第三阶段:精通应用框架的原理,尤其是对IoC的理解及其在Android应用框架中的应用,精通基本的23种设计模式在Android中的应用;

        第四阶段:精通JNI,熟练Android类库中C/C++组件开发;并能够使用JNI机制把现有的C/C++组件移植成为应用框架的核心组件;具备修改和编写自己的应用框架的能力;

        第五阶段:做出自己的Android系统,无论是底层还是上层都能够了如指掌;能够根据实际需要设计和实现比较大Android系统,例如带领比较大的团队做出自己的Android手机产品等;

        第六阶段:势。一切的思考均进入“势”的思考,一切都是思路问题,判断和预测Android的形势,引领市场,通往自由的天堂。


       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值