web-dev-qa-db-fra.com

Singleton dans Android

J'ai suivi ce lien et réussi à faire la classe singleton sous Android. http://www.devahead.com/blog/2011/06/extending-the-Android-application-class-and-dealing-with-singleton/

Le problème est que je veux un seul objet. comme si j'avais l'activité A et l'activité B. Dans l'activité A, j'accède à l'objet de Singleton class. J'utilise l'objet et y ai apporté quelques modifications.

Lorsque je passe à l'activité B et que j'accède à l'objet à partir de Singleton Class, il m'a donné l'objet initialisé et ne conserve pas les modifications que j'ai apportées dans l'activité A. Existe-t-il un autre moyen de sauvegarder les modifications? S'il vous plaît aidez-moi des experts. C'est MainActivity

public class MainActivity extends Activity {
    protected MyApplication app;        
    private OnClickListener btn2=new OnClickListener() {    
        @Override
        public void onClick(View arg0) {
            Intent intent=new Intent(MainActivity.this,NextActivity.class);
            startActivity(intent);              
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Get the application instance
        app = (MyApplication)getApplication();

        // Call a custom application method
        app.customAppMethod();

        // Call a custom method in MySingleton
        Singleton.getInstance().customSingletonMethod();

        Singleton.getInstance();
        // Read the value of a variable in MySingleton
        String singletonVar = Singleton.customVar;

        Log.d("Test",singletonVar);
        singletonVar="World";
        Log.d("Test",singletonVar);

        Button btn=(Button)findViewById(R.id.button1);
        btn.setOnClickListener(btn2);
    }

}

C'est NextActivity

public class NextActivity extends Activity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_next);

            String singletonVar = Singleton.customVar;

            Log.d("Test",singletonVar);
        }
  }

Singleton Classe

public class Singleton
{
    private static Singleton instance;

    public static String customVar="Hello";

    public static void initInstance()
    {
    if (instance == null)
    {
      // Create the instance
      instance = new Singleton();
    }
    }

    public static Singleton getInstance()
    {
     // Return the instance
     return instance;
     }

     private Singleton()
     {
     // Constructor hidden because this is a singleton
     }

     public void customSingletonMethod()
     {
     // Custom method
     }
 }

et MyApplication

public class MyApplication extends Application
    {
    @Override
    public void onCreate()
    {
    super.onCreate();

     // Initialize the singletons so their instances
     // are bound to the application process.
     initSingletons();
     }

     protected void initSingletons()
     {
     // Initialize the instance of MySingleton
     Singleton.initInstance();
     }

     public void customAppMethod()
     {
     // Custom application method
    }
}

Lorsque j'exécute ce code, je reçois Hello, que j'ai initialisé dans Singleton puis World, que je lui ai donné dans MainActivity et qui affiche encore Hello dans NextActivity dans logcat. Je veux qu'il montre à nouveau le monde dans NextActivity. S'il vous plaît aidez-moi à corriger cela.

68
user2216292

EDIT:

L'implémentation d'un Singleton dans Android n'est pas "sûre" ( voir ici ) et vous devriez utiliser une bibliothèque dédiée à ce type de modèle comme Dagger ou une autre bibliothèque DI pour gérer le cycle de vie et l'injection.


Pourriez-vous poster un exemple de votre code?

Jetez un oeil à cette Gist: https://Gist.github.com/Akayh/5566992

ça marche mais ça a été fait très vite:

MyActivity: définit le singleton pour la première fois + initialise l'attribut mString ("Hello") dans un constructeur privé et affiche la valeur ("Hello")

Définissez la nouvelle valeur sur mString: "Singleton"

Lancez activityB et affichez la valeur mString. "Singleton" apparaît ...

45
Akayh

Astuce: Pour créer une classe singleton Dans Android Studio, cliquez avec le bouton droit de la souris sur votre projet et ouvrez le menu:

New -> Java Class -> Choose Singleton from dropdown menu

enter image description here

58
Lazy

C'est simple, en Java, Android prend également en charge singleton. -

Singleton fait partie du modèle de conception de Gang of Four et est classé dans les modèles de conception.

-> Membre statique: contient l'instance de la classe singleton.

-> Constructeur privé: Ceci empêchera quiconque d'instancier la classe Singleton.

-> Méthode publique statique: Ceci fournit le point d'accès global à l'objet Singleton et renvoie l'instance à la classe appelante client.

  1. créer une instance privée
  2. créer un constructeur privé
  3. utiliser getInstance () de la classe Singleton

    public class Logger{
    private static Logger   objLogger;
    private Logger(){
    
            //ToDo here
    
    }
    public static Logger getInstance()
    {
        if (objLogger == null)
       {
          objLogger = new Logger();
       }
       return objLogger;
       }
    
    }
    

en utilisant singleton -

Logger.getInstance();
31
Rakesh

la réponse suggérée par rakesh est excellente, mais toujours avec une discription, Singleton dans Android est identique à Singleton en Java: le modèle de conception Singleton répond à toutes ces préoccupations. Avec le motif de conception Singleton, vous pouvez:

1) Assurez-vous qu'une seule instance d'une classe est créée

2) Fournir un point d'accès global à l'objet

3) Autoriser plusieurs instances dans le futur sans affecter les clients d'une classe singleton

Exemple de classe Singleton de base:

public class MySingleton
{
    private static MySingleton _instance;

    private MySingleton()
    {

    }

    public static MySingleton getInstance()
    {
        if (_instance == null)
        {
            _instance = new MySingleton();
        }
        return _instance;
    }
}
18
ashish.n

Comme @Lazy l'a déclaré dans cette réponse , vous pouvez créer un singleton à partir d'un modèle dans Android Studio. Il est à noter qu'il n'est pas nécessaire de vérifier si l'instance est nulle, car la variable statique ourInstance est d'abord initialisée. En conséquence, l'implémentation de la classe singleton créée par Android Studio est aussi simple que le code suivant:

public class MySingleton {
    private static MySingleton ourInstance = new MySingleton();

    public static MySingleton getInstance() {
        return ourInstance;
    }

    private MySingleton() {
    }
}
12
Adam

Vous copiez la variable customVar du singleton dans une variable singletonVar et sa modification n'affecte pas la valeur d'origine du singleton.

// This does not update singleton variable
// It just assigns value of your local variable
Log.d("Test",singletonVar);
singletonVar="World";
Log.d("Test",singletonVar);

// This actually assigns value of variable in singleton
Singleton.customVar = singletonVar;
5
Dusan

Je mets ma version de Singleton ci-dessous:

public class SingletonDemo {
    private static SingletonDemo instance = null;
    private static Context context;

    /**
     * To initialize the class. It must be called before call the method getInstance()
     * @param ctx The Context used

     */
    public static void initialize(Context ctx) {
     context = ctx;
    }

    /**
     * Check if the class has been initialized
     * @return true  if the class has been initialized
     *         false Otherwise
     */
    public static boolean hasBeenInitialized() {
     return context != null;

    }

    /**
    * The private constructor. Here you can use the context to initialize your variables.
    */
    private SingletonDemo() {
        // Use context to initialize the variables.
    }

    /**
    * The main method used to get the instance
    */
    public static synchronized SingletonDemo getInstance() {
     if (context == null) {
      throw new IllegalArgumentException("Impossible to get the instance. This class must be initialized before");
     }

     if (instance == null) {
      instance = new SingletonDemo();
     }

     return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Clone is not allowed.");
    }
}

Notez que la méthode initialize peut être appelée dans la classe principale (Splash) et que la méthode getInstance peut être appelée à partir d'autres classes. Cela résoudra le problème lorsque la classe appelante requiert le singleton, mais elle n’a pas le contexte.

Enfin, la méthode hasBeenInitialized est utilisée pour vérifier si la classe a été initialisée. Cela évitera que différentes instances aient des contextes différents.

2
jiahao

La manière la plus propre et la plus moderne d’utiliser des singletons dans Android consiste simplement à utiliser le cadre Dependency Injection appelé Dagger 2 . Ici vous avez une explication des portées possibles que vous pouvez utiliser. Singleton est l'un de ces domaines. L'injection de dépendance n'est pas si facile, mais vous devrez investir un peu de votre temps pour le comprendre. Cela facilite également les tests.

1
unlimited101