上一篇我们简单的介绍了一下RoboGuice的使用(【五】注入框架RoboGuice使用:(Your First POJO Injection)),今天我们来看下单例以及上下文单例(ContextSingletons)使用注解的方法,从上一篇文章中相信大家对于普通Java对象(POJO)注解已经很熟悉了。
(一)概述:简要使用方法
①:创建继承RoboActivity的Activity类
②:使用@Inject进行注解POJO(普通Java对象)
③:使用@Singleton进行注解POJO类
(二)下面我们来实现一个单例注解
<span style="font-size:18px;">class MyActivity extends RoboActivity { @Inject Foo foo; // this will basically call new Foo(); }</span>
上面代码的例子中,我们知道每一次MyActivity实例没创建的时候,就会创建一个Foo新的实例。
如果我们现在使用@Singleton进行注解Foo类,RoboGuice就只会初始化一个Foo实例,并且是同样的实例。
<span style="font-size:18px;">@Singleton //a single instance of Foo is now used though the whole app class Foo { }</span>
在这种情况下
<pre name="code" class="java">new MyRoboActivity().foo = new MyRoboActivity().foo
(三)注意:当你使用@Singleton进行注解的时候,你会创建一个不被垃圾回收期收集的对象。当应用程序自身被销毁的时候该对象才会被销毁。即使你的Activity不适用它,只要应用还在运行着,该对象就会一直在内容中。正因为这个原因所以我们如果没有正确的时候它,就会可能出现内存泄露。针对这个情况,我们可以通过下面的上下文单例(ContextSingleton)来解决。
(四):Context Singletons
和@Singleton注解相比较,通过@ContextSingleton来注解创建的单例会根据Context(上下文)的生命周期,然后垃圾回收期(GC)进行回收。下面是使用方法:
@ContextSingleton //a single instance of Foo is now used per context class Foo { }
在上面的例子中,Foo会在Context范围弄有且只会创建一个实例。这就意味着两个MyActivity的实例会具有两个不同的Foo实例(与使用@Singleton注解相反,在这种情况下一个单例会在Activities中进行共享)。但是在同一个Context(上下文)中,Foo有且只会被实例化一次(与不适用@Singleton或者@ContextSingleton相反,这种情况下每次注解会创建一个不同Foo实例)。
详情请看:
public MyActivity extends RoboActivity { @Inject Foo foo; @Inject Bar bar; } public class Foo { @Inject Bar bar; } @ContextSingleton public class Bar { }
在这种情况下:
new MyRoboActivity().foo != new MyRoboActivity().foo MyRoboActivity a = new MyRoboActivity(); a.bar == a.foo.bar
【注意】当你使用@ContextSingleton注解的时候,你创建的对象在给定的上下文生命周期中是不会被垃圾回收期回收。该会当上下文Context销毁的时候被销毁,但是如果你的Context没有使用到它,那么它还会存在内存中。也就是说如果你没有正确使用@ContextSingleton,该还是会出现内容泄露的情况。例如当我们在使用Fragments的时候。请看下面使用@FragmentSingleton。
(五):RoboGuice 3.0
RoboGuice 3.0版本新增了一个类FragmentScope.java,该范围会横跨整个Fragment的生命周期,在这范围内进行注解该会随着fragment生命周期存在,当fragment销毁的时候才会被销毁。
使用FragmentScope,我们同样可以定义单例。每一个FragmentSingleton会在FragmentScope中只会实例化一次。
public MyFragment extends RoboFragment { @Inject Foo foo; @Inject Bar bar; } public class Foo { @Inject Bar bar; } @FragmentSingleton public class Bar { }
在上面的情况下,每一个注解的字段:@Inject Foo foo,都会过的不同的foo实例对象。相反的所得@Inject Bar bar注解的,在相同的FragmentScope中只会获得相同的bar实例对象。
例如,在上面的例子中。
myFragment.bar = myFragment.foo.bar new MyFragment().bar = new MyFragment().foo.bar