English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Detailed Explanation of Singleton Pattern Example in Android Programming Design Patterns

This article gives an example of the Singleton pattern in Android programming design. Shared for everyone's reference, as follows:

One, Introduction

The Singleton pattern is one of the most widely used patterns, and it may also be the only design pattern that many junior engineers are familiar with. When applying this pattern, the class of the Singleton object must ensure that only one instance exists. Many times, the entire system only needs to have one global object, which is beneficial for coordinating the overall behavior of the system.

Two, Definition

Ensure that a class has only one instance, and it should instantiate itself and provide this instance to the entire system.

Three, Application Scenarios

Ensure that a class has only one object, to avoid excessive resource consumption when multiple objects are created, or when only one object of a certain type should exist. For example, if creating an object requires a lot of resources, such as accessing IO and database resources, then it is necessary to consider using the Singleton pattern.

Four, Implementation Methods

1、Eager Initialization Pattern

Example code:

/**
 * Eager Initialization Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance == null){
      instance = new Singleton();
    
    return instance;
  

Advantages:Lazy loading (load only when needed)

Disadvantages:Not thread-safe, it is easy to encounter unsynchronized situations in multi-threaded environments, such as frequent read and write operations on database objects.

2、Lazy Initialization Pattern

Example code:

/**
 * Lazy Initialization Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static synchronized Singleton getInstance() {
    if(instance == null){
      instance = new Singleton();
    
    return instance;
  

Compared to the饿汉模式, the synchronized keyword is added to the getInstance() method, which means that getInstance is a synchronized method, and this is the means to ensure the uniqueness of the singleton object under multi-threading conditions. However, when you think about it, you may find a problem. Even though instance has been initialized (instance will be initialized on the first call), synchronization is still performed each time the getInstance method is called, which will consume unnecessary resources. This is the biggest problem of the lazy loading pattern.

Advantages:It solves the problem of thread safety.

Disadvantages:It is necessary to instantiate it in time when loaded for the first time, and it is slightly slow. The biggest problem is that each call to getInstance performs synchronization, causing unnecessary synchronization overhead.

Supplement:The single instance method used in Android source code, such as InputMethodManager, AccessibilityManager, etc., all use this singleton pattern

3、Double Check Lock(DCL) Double-Checked Locking

Example code:

/**
 * Double-Checked Locking (DCL) Singleton Pattern
 */
public class Singleton {
  private static Singleton instance;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance == null){
      synchronized (Singleton.class) {
        if(instance == null) {
          instance = new Singleton();
        
      
    
    return instance;
  

The highlight of this program is naturally the getInstance method, where you can see that the getInstance method performs two null checks on instance: the first level check is mainly to avoid unnecessary synchronization, and the second level check is to create an instance in the case of null.

Assuming thread A executes to the statement instance = new Singleton(), it looks like a single line of code, but in fact it is not an atomic operation. This line of code will eventually be compiled into multiple assembly instructions, which roughly does3A matter:

(1)allocates memory for a Singleton instance;

(2)calls the constructor of Singleton(), initializes member fields;

(3)points the instance object to the allocated memory space (at this point, instance is no longer null).

However, due to the processor's ability to execute out of order allowed by the Java compiler, as well as JDK1.5the order of the second and third sentences above cannot be guaranteed due to the specification of the order of write-back from Cache, register to main memory in the JMM (Java Memory Model), that is, the execution order may be1-2-3it may also be1-3-2If it is the latter, and3Execution completed,2Before execution, it is switched to thread B, at this time, instance because it has been executed the third point in thread A, instance is non-null, all, thread B directly takes instance, and when used again, it will fail, this is the DCL failure problem, and such difficult-to-track and difficult-to-reproduce errors may hide for a long time.

In JDK1.5After that, SUN officially noticed this problem, adjusted the JVM, and clarified the volatile keyword, so if the JDK is1.5or later versions, you just need to change the definition of instance to private volatile static Singleton instance to ensure that the instance object is read from the main memory each time, and you can use the DCL writing method to complete the singleton pattern. Of course, volatile will affect performance to some extent, but considering the correctness of the program, it is still worth sacrificing this performance.

Advantages: High resource utilization, the singleton object is instantiated only when getInstance is executed for the first time, which is efficient. In scenarios with low concurrency and low security, the singleton pattern may run perfectly.

Disadvantages: The response is slightly slow when loaded for the first time, and it may fail occasionally due to the Java memory model. There are also certain defects in high-concurrency environments, although the probability is very low.

Supplement: In the open-source Android image project Android-Universal-Image-Loader (https://github.com/nostra13/Android-Universal-Image-Loader) uses this method.
DCL pattern is the most commonly used singleton implementation method, which can instantiate the singleton object only when needed and can ensure the uniqueness of the singleton object in most scenarios, unless your code is more complex in concurrent scenarios or below JDK6version, otherwise, this method generally meets the needs.

4Static inner class singleton pattern

DCL, although it solves problems such as resource consumption, redundant synchronization, and thread safety to some extent, still fails in some cases. This problem is known as DCL failure, and it is mentioned at the end of the book 'Java Concurrency in Practice', pointing out that this 'optimization' is ugly and not recommended for use. Instead, it suggests using the following code as an alternative:

Example code:

/**
 * Static inner class singleton pattern
 */
public class Singleton {
  private Singleton(){}
  public static Singleton getInstance(){
    return SingletonHolder.instance;
  
  /**
   * Static inner class
   * Lazy loading, reducing memory overhead
   */
  private static class SingletonHolder{}}
    private static final Singleton instance = new Singleton();
  

When the Singleton class is loaded for the first time, instance will not be initialized. It is only when the getInstance method of Singleton is called for the first time that instance will be initialized. Therefore, the first call to getInstance method will cause the virtual machine to load the SingletonHolder class. This method not only ensures thread safety but also ensures the uniqueness of the singleton object, and also delays the instantiation of the singleton, so this is the recommended implementation of the singleton pattern.

Advantages: Lazy loading, thread-safe (mutually exclusive when class is loaded in java), and also reduces memory consumption

5, Enum singleton

Some implementations of the singleton pattern have been explained before, but these implementations are somewhat麻烦 or may have problems in some cases.

Example code:

/**
 * Enum singleton pattern
 */
public enum Singleton {
  /**
   * 1.From Java1.5Start to support;
   * 2.Provide serialization mechanism for free;
   * 3.Absolutely prevent multiple instantiation, even in the face of complex serialization or reflection attacks;
   */
  instance;
  private String others;
  Singleton() {
  
  public String getOthers() {
    return others;
  
  public void setOthers(String others) {
    this.others = others;
  

Simplicity in writing is the biggest advantage of enum singleton, enum is the same as a common class in Java, which can not only have fields but also have its own methods. Most importantly, the creation of default enum instances is thread-safe, and it is always a singleton under any circumstances.

Why is that? In the above several implementations of the singleton pattern, there is a situation where they will re-create objects, that is, deserialization.

Serialization can write a singleton instance object to disk and then read it back to effectively obtain an instance. Even if the constructor is private, a new instance of the class can still be created during deserialization through special means, which is equivalent to calling the constructor of the class. The deserialization operation provides a special hook function, a private method readResolve() in the class, which allows developers to control the deserialization of the object. For example, if it is necessary to prevent the singleton object from being re-generated when deserialized in the above several examples, the following method must be added:

private Object readResolve() throws ObjectStreamException {
  return instance;

That is, returning the instance object in the readResolve method instead of creating a new object by default. For enumeration, this problem does not exist because it will not create a new instance even if it is deserialized.

Advantages: Provide free serialization mechanism, absolutely prevent multiple instantiation, even in the face of complex serialization or reflection attacks.

Disadvantages: From Java1.5Start supporting.

The above mainly talks about the Singleton pattern5There are many creation methods, and everyone can choose to use them in their actual projects according to their advantages and disadvantages.

Readers who are interested in more content related to Android can check the special topics on this site: 'Android Development入门与进阶教程', 'Android Debugging Skills and Common Problem Solving Methods Summary', 'Summary of Android Basic Component Usage', 'Summary of Android View View Skills', 'Summary of Android Layout Layout Skills', and 'Summary of Android Control Usage'.

I hope this article will be helpful to everyone in designing Android programs.

Declaration: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been edited by humans, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please replace # with @ when sending an email to report abuse, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.

You May Also Like