回顾这篇文章,列举了使用单例对象的几个问题 并且已经看到了几个使用单例模式的Android应用程序的例子,我想知道使用单例而不是通过全局应用程序状态共享的单个实例是否是一个好主意(子类化Android .os. application并通过context.getApplication()获取它)。

这两种机制有什么优点/缺点?

老实说,我希望在这篇文章中得到同样的答案,单例模式与Web应用程序,不是一个好主意!但应用于Android。我说的对吗?DalvikVM有什么不同?

编辑:我想就所涉及的几个方面发表意见:

同步 可重用性 测试


当前回答

我也有同样的问题:单例还是做一个子类android.os.Application?

首先,我尝试了单例,但我的应用程序在某些时候会调用浏览器

Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));

问题是,如果手机没有足够的内存,你的大多数类(甚至是单例)被清理以获得一些内存,当从浏览器返回到我的应用程序时,它每次都崩溃了。

解决方案:将需要的数据放在Application类的子类中。

其他回答

我的观点是:

我确实注意到,当我的活动被销毁时,一些单例/静态字段被重置。我在一些低端2.3设备上注意到了这一点。

我的案例非常简单:我只有一个私有文件“init_done”和一个静态方法“init”,我从activity.onCreate()调用。我注意到init方法在重新创建活动时重新执行了自己。

虽然我不能证明我的肯定,这可能与单例/类是什么时候第一次创建/使用有关。当活动被销毁/回收时,似乎只有这个活动引用的所有类也都被回收了。

我把我的singleton实例移动到Application的一个子类。我从应用程序实例访问它们。而且,从那以后,再也没有注意到这个问题。

我希望这能帮助到一些人。

应用程序与单例不一样。原因如下:

应用程序的方法(如onCreate)在ui线程中调用; Singleton的方法可以在任何线程中调用; 在Application的onCreate方法中,可以实例化Handler; 如果单例是在无ui线程中执行的,则不能 实例化处理程序; 应用程序具有管理的生命周期的能力 activity。它有方法 “registerActivityLifecycleCallbacks”。但是单身人士没有 能力。

我非常不同意Dianne Hackborn的回答。我们一点一点地从我们的项目中移除所有的单例对象,以支持轻量级的、任务范围的对象,当你真正需要它们时,它们可以很容易地重新创建。

单例是测试的噩梦,如果延迟初始化,将引入带有微妙副作用的“状态不确定性”(当将对getInstance()的调用从一个作用域移动到另一个作用域时,可能会突然出现)。可见性是另一个问题,由于单例意味着对共享状态的“全局”(=随机)访问,在并发应用程序中没有正确同步时,可能会出现微妙的错误。

我认为这是一种反模式,它是一种糟糕的面向对象风格,本质上相当于维护全局状态。

回到你的问题:

虽然应用程序上下文本身可以被认为是一个单例,但它是由框架管理的,并且具有定义良好的生命周期、作用域和访问路径。因此,我认为如果你确实需要管理app-global状态,它应该放在这里,而不是其他地方。对于其他任何事情,重新考虑是否真的需要一个单例对象,或者是否也可以重写单例类来实例化执行手头任务的小型、短期对象。

我也有同样的问题:单例还是做一个子类android.os.Application?

首先,我尝试了单例,但我的应用程序在某些时候会调用浏览器

Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));

问题是,如果手机没有足够的内存,你的大多数类(甚至是单例)被清理以获得一些内存,当从浏览器返回到我的应用程序时,它每次都崩溃了。

解决方案:将需要的数据放在Application类的子类中。

同时考虑这两者:

将单例对象作为类中的静态实例。 拥有一个公共类(Context),它为应用程序中的所有单例对象返回单例实例,这样做的好处是Context中的方法名将是有意义的,例如:Context . getloggedinuser()而不是User.getInstance()。

此外,我建议您扩展上下文,不仅包括对单例对象的访问,还包括需要全局访问的一些功能,例如:Context . logoffuser (), Context . readsaveddata()等。也许将Context重命名为Facade会有意义。