Singletons vs. Application Context in Android?

后端 未结 10 1328
醉话见心
醉话见心 2020-11-22 03:11

Recalling this post enumerating several problems of using singletons and having seen several examples of Android applications using singleton pattern, I wonder if it\'s a go

相关标签:
10条回答
  • 2020-11-22 03:18

    I very much disagree with Dianne Hackborn's response. We are bit by bit removing all singletons from our project in favor of lightweight, task scoped objects which can easiliy be re-created when you actually need them.

    Singletons are a nightmare for testing and, if lazily initialized, will introduce "state indeterminism" with subtle side effects (which may suddenly surface when moving calls to getInstance() from one scope to another). Visibility has been mentioned as another problem, and since singletons imply "global" (= random) access to shared state, subtle bugs may arise when not properly synchronized in concurrent applications.

    I consider it an anti-pattern, it's a bad object-oriented style that essentially amounts to maintaining global state.

    To come back to your question:

    Although the app context can be considered a singleton itself, it is framework-managed and has a well defined life-cycle, scope, and access path. Hence I believe that if you do need to manage app-global state, it should go here, nowhere else. For anything else, rethink if you really need a singleton object, or if it would also be possible to rewrite your singleton class to instead instantiate small, short-lived objects that perform the task at hand.

    0 讨论(0)
  • 2020-11-22 03:20

    From the proverbial horse's mouth...

    When developing your app, you may find it necessary to share data, context or services globally across your app. For example, if your app has session data, such as the currently logged-in user, you will likely want to expose this information. In Android, the pattern for solving this problem is to have your android.app.Application instance own all global data, and then treat your Application instance as a singleton with static accessors to the various data and services.

    When writing an Android app, you're guaranteed to only have one instance of the android.app.Application class, and so it's safe (and recommended by Google Android team) to treat it as a singleton. That is, you can safely add a static getInstance() method to your Application implementation. Like so:

    public class AndroidApplication extends Application {
    
        private static AndroidApplication sInstance;
    
        public static AndroidApplication getInstance(){
            return sInstance;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            sInstance = this;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 03:21

    Consider both at the same time:

    • having singleton objects as static instances inside the classes.
    • having a common class (Context) that returns the singleton instances for all the singelton objects in your application, which has the advantage that the method names in Context will be meaningful for example: context.getLoggedinUser() instead of User.getInstance().

    Furthermore, I suggest that you expand your Context to include not only access to singleton objects but some functionalities that need to be accessed globally, like for example: context.logOffUser(), context.readSavedData(), etc. Probably renaming the Context to Facade would make sense then.

    0 讨论(0)
  • 2020-11-22 03:21

    My 2 cents:

    I did notice that some singleton / static fields were reseted when my activity was destroyed. I noticed this on some low end 2.3 devices.

    My case was very simple : I just have a private filed "init_done" and a static method "init" that I called from activity.onCreate(). I notice that the method init was re-executing itself on some re-creation of the activity.

    While I cannot prove my affirmation, It may be related to WHEN the singleton/class was created/used first. When the activity get destroyed/recycled, it seem that all class that only this activity refer are recycled too.

    I moved my instance of singleton to a sub class of Application. I acces them from the application instance. and, since then, did not notice the problem again.

    I hope this can help someone.

    0 讨论(0)
  • 2020-11-22 03:22

    Application is not the same as the Singleton.The reasons are:

    1. Application's method(such as onCreate) is called in the ui thread;
    2. singleton's method can be called in any thread;
    3. In the method "onCreate" of Application,you can instantiate Handler;
    4. If the singleton is executed in none-ui thread,you could not instantiate Handler;
    5. Application has the ability to manage the life cycle of the activities in the app.It has the method "registerActivityLifecycleCallbacks".But the singletons has not the ability.
    0 讨论(0)
  • 2020-11-22 03:26

    I very much recommend singletons. If you have a singleton that needs a context, have:

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

    I prefer singletons over Application because it helps keep an app much more organized and modular -- instead of having one place where all of your global state across the app needs to be maintained, each separate piece can take care of itself. Also the fact that singletons lazily initialize (at request) instead of leading you down the path of doing all initialization up-front in Application.onCreate() is good.

    There is nothing intrinsically wrong with using singletons. Just use them correctly, when it makes sense. The Android framework actually has a lot of them, for it to maintain per-process caches of loaded resources and other such things.

    Also for simple applications multithreading doesn't become an issue with singletons, because by design all standard callbacks to the app are dispatched on the main thread of the process so you won't have multi-threading happening unless you introduce it explicitly through threads or implicitly by publishing a content provider or service IBinder to other processes.

    Just be thoughtful about what you are doing. :)

    0 讨论(0)
提交回复
热议问题