[菜鸟笔记]Android开发-代理
很长时间没有上来了,今天就来总结一下最近的心得.
以前各种开发中的模式都多多少少研究过一些,但是最近对代理深有体会,确实很有用.看到这里应该很多人已经知道了本人是一个菜鸟.确实是,我的确算是个菜鸟.
所以在这里写这些东西不是要告诉大家一个高深的技术,而是本人的一个笔记性的东西,主要目的就是让自己有一些东西可以沉淀下来.当然也欢迎各位大侠或是菜鸟的指正.
进入正题.那么关于代理,一般我们是在什么情况下用到代理呢,就我的理解,应该是在我们需要重写一些系统的方法的时候,比如,假如,这里说的是假如,假如有一天,我们在做一个项目的时候,有这样的需求,就是这个项目所有的图片资源必须都是来自网络,而项目中的图片都不能被使用,那么我们应该怎么实现这个需求呢,首先我们想到的一定是重写Activity的getResources()方法,然后重写Resources类中的getDrawable(int id)这个方法.但是问题出现了,如果我们自己写个类直接重写了getDrawable()方法,有用吗?没有!为什么呢,因为Resource是Activity的getResource()这个方法返回的(这个方法其实是Context的).我们又不能跟Google说你把你的Resources这个类的getDrawable()这个方法的返回值都改成null吧,这样我们上面所说的需求就实现了.但是那是不可能的.google不会听你的,这个时候就要用到代理了.
代理其实就是有一个空壳将我们请求的所有东西转到另一个实体去实现,代理本身并不处理数据,只是做跳板.
还是说上面的需求.用代理怎么实现呢?
首先我们要做的就是写一个类,暂且叫做MyResources,这个类继承自Resources,并且我们要在这个类里面重写父类的所有public的方法,记住是所有.并且在这个类中有一个属性,一个Resources的引用,例如:
1 private Resources mBaseResources;
并且需要有一个针对这个属性的构造方法.
然后,在MyResources的每一个重写的方法中都添加具体实现,具体实现就是:所有的实现都是由属性"mBaseResources"调用重写的对应的方法来实现,例如我们在MyResources中重写了父类的getId()这个方法,那么被重写的这个方法应该是这样的:
1 @override 2 public int getId() 3 { 4 return mBaseResources.getId(); 5 }
即所有的实现都由mBaseResources这个对象完成.
那么这个mBaseReources从哪儿来呢,上面不是说过需要写一个针对mBaseResources的构造器吗,我们需要在重写Activity的getResource()的时候,方法是在重写的这个方法里返回我们的MyResources对象,并且在new我们的MyResources对象时将系统Activity自己的getResources()方法返回的Resources对象在构造器里赋值给mBaseResources这个引用.一切尽在代码中:(Activity中重写getResources()方法)
1 @override 2 public Resources getResources() 3 { 4 return new MyResources(super.getResources()); 5 }
这样,我们在Activity中通过getResources()方法获得的对想其实是Resources的子类MyResources的.而在MyResources这个对象中所有方法的实现其实都是调用super.getResources()返回的对象的相应的方法实现的.
到这里就完了吗,没有.如果仅仅是做了上面这些的话,那么我们的代理就没有一点作用了,因为所有的实现都是super的Resources对象实现的,这和我们直接不重写getResources()方法不是没有任何差别吗.对,所以这里要说我们一开始说的需求,就是,重写getDrawable()这个方法,其实上面已经重写了, 就是在MyResources里,而在MyResources()方法里的实现是这样的"return mBaseResource.getDrawable();".现在我们的需求是不使用本地的图片,那么直接该这个方法为"return null;"就可以了.
这样,就完成了,这样所有我们在Activity中通过getResources().getDrawable()返回的就永远是null了.
当然,上面所说的需求,还有重写getResources()的方法,都是做一个例子,大家不要纠结什么"你忘了在layout中的drawable的id处理了!!!".上面只是对代理的一个最基本的实现做个简单的描述.
而上面的MyResoures就叫做包装类,包装类具体不关心实现,只是做一个跳板,其中的对所有的public方法的实现都是由正统的Activity的getResource()方法返回的Resouces对象实现的,但是除了我们需要特变改变的getDrawable()这个方法,在这里我们主要按照自己的需求重写就可以了.
在这里代理就说完了, 那么还有一个重要的事情要说,就是上面的这个例子只是个例子,因为,Resources这个类中有4,5个public的final的方法,final方法是不能被重写的,所以上面说的这个只是个例子.也需有人会说"那就不要重写这几个方法不就得了".但是我这里要说的是不可以,每一个方法中的实现必然会牵涉Resources对象中的变量的引用或是改变,如果不重写,那么这些final的实现就个那个mBaseReources没有关系了,就相当于空实现了,这样是绝对不可取的.所以如果你不明白这一段,那么只要记着如果有需求,那么注意需要包装的类的所有public的方法,如果有final的方法,那么这里是不能用代理的.
如果你明白上面说的为什么有public final方法的类不能用代理的话,那么我在这里要说的是,有些情况下其实也是可以的.例如一个类中有一个"public final Theme getTheme()"方法,那么照上面说的,这个类就不能被包装,这里就不能用代理,但是如果这个方法里的实现只是这样呢:
1 @override 2 public final Theme getTheme() 3 { 4 return new Theme(); 5 }
那么我们重写或是不重写这个方法效果是一样的.
所以这里还是可以代理的,只是在在包装来中不需要重写这个方法了,当然,也没有办法重写.
还有一个,就是final类就真的没有办法了,final类是不可以被重写的,所以不能用包装类,不能用代理.
综上所述,代理在一些情况一下,尤其是在我们重写一些父类的有返回对象的方法时很有用.希望对大家有用.