tags:

views:

134

answers:

3

I'm considering creating a singleton wrapper for a Context so my model objects, if necessary, can open and read from a database connection. My model objects do not have access to a Context, and I'd like to avoid needing to pass a reference to a Context from object to object.

I was planning to place into this singleton a reference to the Context returned by Application.getApplicationContext(). This singleton object would be initialized in my custom Application instance before anything else would need to or have a chance to use it.

Can anyone think of a reason to not do this?

A: 

I'm not sure I get your idea, but here's what's been working for me:

public class MyApp extends Application {

private static MyApp instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        // ...
    }

    public static MyApp getInstance(){
        return instance;
    }

    // misc helper methods
}
alex
I pasted my implementation of this in an answer to I could have formatting and line breaks preserved. My class does about the same thing as yours does.
kpdvx
+1  A: 

I would urge you to think about what reasons you have for not passing a reference of the application context into your model objects.

There are various well-documented disadvantages of using singletons. I won't go into detail here but you might want to consider:

  • How singletons limit your ability to properly unit-test your application.
  • Singletons hide dependencies between different entities in the code- you cannot determine dependecies from inspecting the interfaces.
  • You have no real control over the lifetime of a singleton, it could exist for the lifetime of your application. Do you really want to potentially hold a DB connection for the lifetime of your app?
  • The thread safety of your singleton.

If you valid reasons for not passing a reference to a context to other parts of your application then perhaps you should consider some other pattern- a factory might be one possible solution, a service another.

Jack Patmos
Thanks for your reply! For better or for worse I'm not employing any unit tests at the moment, so I'm going to ignore your first warning. Hidden dependencies, yes, this could be a problem but I think this is true of other patterns as well. As for the lifetime, I'm only holding a reference to a Context not to a DB and in Application's onDestroy() I can perform any cleanup to the wrapper. And to your third warning, I've applied proper synchronization to this wrapper. As for a service, I think binding is a bit overkill for this, and a custom factory could not return an application's Context.
kpdvx
Which isn't to say that your warnings aren't valid, rather that I think I can safely account for them, for the most part. Unfortunately the character limit can make replies look terse and unfriendly!
kpdvx
No problem! You've clearly thought about the issues at hand and are happy that the limitations of using singletons is a price you're happy to pay in this instance (and hey- everything has a price, right?) I'm not completely against singletons by any means, but I've seen first-hand the damage that ill-thought out use of them can have (on more than one occassion).
Jack Patmos
A: 

Pasted here to preserve formatting.

public class ContextContainer
{
    private static boolean initialized;
    private static Context context;

    private ContextContainer()
    {
        //
    }

    public static synchronized void setApplicationContext(Context context)
    {
        if (!initialized) {
            ContextContainer.context = context;
            initialized = true;
        } else {
            throw new RuntimeException("ApplicationContext has already been set!");
        }
    }

    public static synchronized Context getApplicationContext()
    {
        return context;
    }
}
kpdvx
I should note that my original implementation was a proper singleton, but I've since chosen to use a static member and accessor.
kpdvx