为什么要用单例模式?
单例模式的定义:“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”Java中单例模式定义;“一个类有且仅有一个实例,并且自行实例化向整个系统提供该实例。”
对于系统中的某些类来说,只有一个实例很重要。例如,记录最新的短信和最新的通话记录的时候;或者,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只有有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID生成器。如在Windows OS 中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着某一瞬间系统有多个状态,与实际不符,也会为用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例是非常重要的。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
Android的单例模式要注意什么?
在使用单例时,要防止出现内存泄漏。
单例模式的静态特性导致它的对象的生命周期是和应用一样的,如果不注意这一点就可能导致内存泄漏。比如说,Context泄漏,如下所示
//SingleInstance.class
private volatile static SingleInstance mSingleInstance = null;
private SingleInstance (Context context) {}
public static SingleInstance getInstance(Context context) {
if (mSingleInstance == null) {
synchronized (SingleInstance.class) {
if (mSingleInstance == null) {
mSingleInstance = new SingleInstance(context);
}
}
}
return mSingleInstance;
}
//MyActivity
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这样就容易出问题了
SingleInstance singleInstance = SingleInstance.getInstance(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
如上面那样直接传入MyActivity的引用,如果当前MyActivity退出了,但应用还没有退出,singleInstance一直持有MyActivity的引用,MyActivity就不能被回收了。
解决方法也很简单,传入ApplicationContext就可以了。
SingleInstance singleInstance = SingleInstance.getInstance(getApplicationContext());
除了Context泄漏外,可能还存在view泄漏等问题,这些在使用单例应多多注意,防止出现内存泄漏。
1个推荐的Android单例模式写法
有一些朋友喜欢用双重检查锁定模式来创建单例,但有时会在多线程环境下创建非唯一的实例(概率较小)。所以我们可以通过volatile关键字来确保只能生成唯一的实例。volatile关键字能够保证可见性,被volatile修饰的变量,在一个线程中被改变时会立刻同步到主内存中,而另一个线程在操作这个变量时都会先从主内存更新这个变量的值。
创建单例的代码如下所示:
private volatile static Singleton mSingleton = null;
private Singleton () {}
public static Singleton getInstance() {
if (mSingleton == null) {
synchronized (Singleton.class) {
if (mSingleton == null) {
mSingleton = new Singleton();
}
}
}
return mSingleton;
}
参考文档