Singleton в Android — зло?


Ранее я использовала Singleton наподобие этого:

public class Singleton { 
    private static Singleton instance; 

    private Singleton (){ 
    } 

    public static Singleton getInstance(){ 
        if (null == instance){ 
           instance = new Singleton(); 
        } 
        return instance; 
    } 
}

Ранее я видела много примеров использования такого класса в андроид-приложениях и различных справочниках. Но наткнулась на статью, в которой был описан недостаток использования такого Singleton в Android:

Мы создаем экземпляр класса Singleton в контексте текущей Activity и если эта Activity завершает свою работу, то и экземпляр класса будет уничтожен (причем не сразу, а когда сработает сборщик мусора Java). А значит при следующем вызове getInstance() объект будет создаваться заново (вновь вызовется конструктор). Если в классе Singleton мы храним какие-то статичные переменные или методы, то это можно просто проигнорировать.

Вот ссылка на статью

Далее в этой статье говорится, что, чтобы избежать такой ошибки, нужно инициализировать синглтон в подклассе класса Application:

public class MyApp extends Application {
   @Override
   public void onCreate() {
      super.onCreate();
      Log.w("MY", "onCreate MyApp");

      MySingleton.initInstance();
   }
}

И сам синглтон:

class MySingleton {
    ...

    public static void initInstance() {
       Log.d("MY", "MySingleton::InitInstance()");
       if (mInstance == null) {
             mInstance = new MySingleton();
       }
    }

    public static MySingleton getInstance() {
      Log.d("MY", "MySingleton::getInstance()");
      return mInstance;
    }

 ...
}

Теперь вне зависимости от того какие activities работают экземпляр класса MySingleton будет существовать.

То есть, это более правильный вариант использования Singleton в Android? Нет ли у этого способа каких-либо недостатков? Хотелось бы узнать вашу точку зрения.

Author: ЮрийСПб, 2016-02-03

2 answers

В случае использования паттерна Singleton при разработке для Android важно помнить две вещи:

  1. Никогда не сохранять в синглтоне ссылку на активити. Если для работы синглтона нужен контекст, используйте контекст приложения. Иначе будут утечки памяти.
  2. Всегда лучше создать приватную переменную в потомке класса Application со ссылкой на экземпляр вместо приватной статической в самом классе сиглтона, если это возможно.

Следуя этим двум простым правилам будет сложнее "выстрелить себе в ногу" :)

 16
Author: Eugene Krivenja, 2016-02-03 13:07:01

А я бы посоветовал еще вот статью «Синглетоны на Android. Как не стукнуться клювом об дерево», в ней как раз таки объясняется, что дело не в сохранении контекста активити в синглтоне:

Вы инициализируете статический класс синглетона в контексте Activity. Если в вашем приложении несколько activity, то синглетон доступен в каждой из них. Но если первоначальная activity, в которой создавался синглетон, будет уничтожена, то и синглетон тоже будет уничтожен. После этого, в других activity вы будете получать null вместо A.

И в коментариях можете увидеть краткое обьяснение этого с отсылкой на СО :-) :

Это архитектурная особенность Android OS. Подробнее можно почитать здесь. Цитирую: "Lifetime of a static variable: A static variable comes into existence when a class is loaded by the JVM and dies when the class is unloaded.

So if you create an android application and initialize a static variable, it will remain in the JVM until one of the following happens: 1. the class is unloaded 2. the JVM shuts down 3. the process dies

Note that the value of the static variable will persist when you switch to a different activity of another application and none of the above three happens. Should any of the above three happen the static will lose its value."

И далее

"Well, the Singleton pattern is also based on using static variables so actually you would be in the same position. While the static approach may work most of the times, it may happen that in some cases when memory is full and another activity takes the foreground before your application moves to its next screen, your activity's process could be killed and you lose the static values."

Https://stackoverflow.com/questions/1944369/android-static-object-lifecycle

 2
Author: mvs, 2018-02-27 07:37:40