Android 中的单例与应用程序上下文?

2022-08-31 04:44:20

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

这两种机制有哪些优点/缺点?

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

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

  • 同步
  • 可 重用
  • 测试

答案 1

我非常不同意Dianne Hackborn的回应。我们正在从我们的项目中逐点删除所有单例,以支持轻量级的任务范围对象,当您实际需要它们时,可以很容易地重新创建它们。

单例是测试的噩梦,如果懒惰地初始化,将引入具有微妙副作用的“状态不确定”(当将调用从一个范围移动到另一个范围时,可能会突然浮出水面)。可见性已被提到是另一个问题,并且由于单例意味着对共享状态的“全局”(=随机)访问,因此在并发应用程序中未正确同步时可能会出现细微的错误。getInstance()

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

回到你的问题:

尽管应用上下文本身可以被视为单例,但它是框架管理的,并且具有明确定义的生命周期、范围和访问路径。因此,我相信,如果你确实需要管理应用程序全局状态,它应该去这里,而不是其他地方。对于其他任何内容,请重新考虑是否真的需要单例对象,或者是否可以重写单例类以实例化执行手头任务的小型短期对象。


答案 2

我非常推荐单例。如果您有一个需要上下文的单例,请具有:

MySingleton.getInstance(Context c) {
    //
    // ... needing to create ...
    sInstance = new MySingleton(c.getApplicationContext());
}

与应用程序相比,我更喜欢单例,因为它有助于使应用程序更加井井有条和模块化 - 而不是在一个地方需要维护整个应用程序的所有全局状态,每个单独的部分都可以自行处理。此外,单例懒惰地初始化(根据请求)而不是引导您走上在 Application.onCreate() 中预先执行所有初始化的路径,这一事实也很好。

使用单例在本质上没有任何错误。只要在有意义的时候正确使用它们。Android框架实际上有很多这样的框架,因为它可以维护加载资源和其他类似内容的每个进程缓存。

同样,对于简单的应用程序,多线程处理不会成为单例的问题,因为根据设计,对应用的所有标准回调都是在进程的主线程上调度的,因此除非您通过线程显式引入多线程或通过将内容提供程序或服务 IBinder 发布到其他进程来隐式引入它,否则不会发生多线程。

只要对你正在做的事情深思熟虑。:)


推荐