0

I am building a singleton service in Java for Android:

final class MyService {

    private static Context context = null;
    // ...

    private MyService() {
        myObj = new MyObj(context);
            // ...  
    }                       
    private static class Singleton {
        private static final MyService INSTANCE = new MyService();
    }

    /**
     *  a singleton - do not use new(), use getInstance().
     */
    static synchronized myService getInstance(Context c) {
        if (context == null) context = c;
        return Singleton.INSTANCE;
    }

To improve performance I use static variables and methods throughout.

My questions:

  • for objects, new() ensures the opportunity to initialize that object before its use. Is there an equivalent for a static class? For example: when static methods depend upon earlier initializations - such as as for 'context' above - is there a means of ensuring that the initialization happens first? Must I throw an exception if they have not?

  • as this is all static I expect that there is only the class itself: is that a singleton by definition? Is the recommended code above just the way of preventing instantiation of objects?

Thanks in advance!

10
  • All services in android are singletons, what are you trying to accomplish? Commented Sep 24, 2010 at 19:47
  • 2
    I would advise against making your singletons stateful (adding context). Those two things are two heavily conflicting anti-patterns. Commented Sep 24, 2010 at 19:49
  • @Falmarri: I am trying to accomplish 1) ensuring a single authoritative source of some methods, 2) maximizing performance. I imagine this is similar to getSystemService() but within a single process (and thus does not need AIDL). My approach so far is to extend Service and then call its methods directly from within other application components (without using intents). Commented Sep 24, 2010 at 20:09
  • @Mark: My service tracks events and offers summaries via getters. This is clearly stateful and also seems a viable candidate for a singleton. Is this an exception - or can you suggest where I might learn more about the anti-pattern? Thx! Commented Sep 24, 2010 at 20:14
  • @Falmarri: I need to add .. my service is runs periodically via an alarm to gather event data and summarize it. That data needs to be available at any time - for example when a widget reads it. I've had my service in memory "permanently" serving the widget, but it occurs to me that I ought to be decoupling these: a periodically run service writing summary data to a content provider, which in turn is read by callers. /me suffers noobish confusion :) Commented Sep 24, 2010 at 20:31

3 Answers 3

2

That's certainly one way to create a singleton. I think you could do away with the static helper; going static for performance reasons really doesn't save much and it obfuscates the code.

I think your real question is whether construction of a static can be delayed until context is not null. The answer depends on the VM; in most "vanilla" Java VMs, INSTANCE would not actually be instantiated until the first call to GetInstance(); statics are lazily evaluated for better startup performance. That means that as long as context got something else before the first call to GetInstance(), you're good.

However, forgive me but I do not know if this behavior differs in the Android VM, which is technically not a "real" Java VM (or so says Sun/Oracle). To be on the safe side, if context doesn't have an instance by the time the static constructor is called, I would look into resolving one in the static constructor using a static factory method or a simple IoC, before instantiating INSTANCE.

Sign up to request clarification or add additional context in comments.

2 Comments

I am composing objects and within them I instantiate and use android classes that require context (e.g. getSharedPreferences). I was using a singleton 'with static' model, thus exposing methods for use without any prior call to getInstance() and the initializations it performs. It seems my first step forward is to abandon 'static' so that getInstance() is ensured - and to study up on when it is proper to use it. Thanks lots to all for helping debug my broken concept!
The VM spec is very specific about the situations in which statics are initialized. While Dalvik is definitely not Java(tm), it does try to follow the rules laid out in the specification.
1

You can add a static initialisation block to your class

public class MySingleton {
    /* Default constructor */
    private MySingleton() {
    }

    static {
          //Static init stuff...
        }
        ...
    }
}

The static initializer block will be called once for each classloader the class is loaded by - so typically, only once during the life of the process.

Finally, by definition your singleton is only going to be created once so there will be no performance benefit from using static helpers to do the job.

2 Comments

Robert, according to my O'Reilly, "if a method is declared with the final{or static] modifier, ... the compiler knows that there is only one version of the method, and dynamic method lookup is not necessary ... and are candidates for inlining ..." Maybe that's what you said? :D
DJC - Sure, but as this case is initailisation for a singleton, the JIT won't bother inlining the call as it's only called once.
0

Avoid overengineering. Use an enum instead.

While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

Joshua Bloch

The approach is explained in this post by Joshua Bloch.

1 Comment

You can also check answers to this StackOverflow question : stackoverflow.com/questions/70689/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.