Singleton în Android (Programare, Android, Singleton)

utilizator2216292 a intrebat.

Am urmat acest link și am făcut cu succes clasa singleton în Android.http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

Problema este că vreau un singur obiect. cum ar fi că am activitatea A și activitatea B. În activitatea A accesez obiectul din Singleton class. Folosesc obiectul și am făcut unele modificări la el.

Când trec la activitatea B și accesez obiectul din clasa Singleton, acesta îmi oferă obiectul inițializat și nu păstrează modificările pe care le-am făcut în activitatea A. Există vreo altă modalitate de a salva modificările? 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);
    }

}

Aceasta este 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 Clasa

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
     }
 }

și 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
    }
}

Când execut acest cod, obțin Hello, pe care l-am inițializat în Singleton apoi World, pe care am inițializat-o în MainActivity și din nou apare Hello în NextActivity în logcat.Vreau să se afișeze din nou World în NextActivity.vă rog să mă ajutați să corectez acest lucru.

Comentarii

  • În MainActivity – de ce apelați Singleton.getInstance() de două ori? –  > Por IgorGanapolsky.
  • Acest lucru s-a întâmplat în principal pentru că atunci când apelați String singletonVar = Singleton.customVar; în java, această operațiune de atribuire nu atribuie referința la Singleton.customVar în memorie, ci pur și simplu creează o nouă variabilă numită singletonVar și, prin urmare, atunci când schimbați SingletonVar, pur și simplu schimbați valoarea variabilei locale, nu a variabilei singleton. –  > Por M_AWADI.
  • Vechi, dar, String singletonVar = Singleton.customVar; String este un tip primitiv, deci nu este un obiect, pur și simplu copiați valoarea curentă din singleton în variabila locală, apoi modificați valoarea variabilei locale.  > Por Pecana.
  • Linkul este greșit –  > Por Slaknation.
8 răspunsuri
Akayh

EDIT :

Implementarea unui Singleton în Android nu este „sigură” (a se vedea aici) și ar trebui să folosiți o bibliotecă dedicată acestui tip de model, cum ar fi Dagger sau o altă bibliotecă DI pentru a gestiona ciclul de viață și injecția.


Ați putea posta un exemplu din codul dumneavoastră?

Aruncați o privire la acest gist : https://gist.github.com/Akayh/5566992

funcționează, dar a fost făcut foarte repede:

MyActivity : setați singletonul pentru prima dată + inițializați atributul mString („Hello”) în constructorul privat și afișați valoarea („Hello”)

Setați o nouă valoare la mString : „Singleton”

Lansați activitateaB și afișați valoarea mString. Apare „Singleton”…

Comentarii

  • Acesta este un exemplu de cod de singleton între activități. Dacă aveți nevoie de mai mult ajutor, postați codul dvs. (sau un exemplu simplu) pentru a vedea problema –  > Por Akayh.
  • Este doar pentru că șirul este copiat în singletonVar și nu o referință la acesta. Dacă modificați direct variabila statică după cum urmează : Singleton.customVar=”World”; va funcționa. –  > Por Akayh.
  • Doar o mică atenționare, aceasta este NU sigur pentru fire! Întotdeauna, amintiți-vă de Legea lui Murphy. O modalitate de a face acest lucru în siguranță este să folosiți synchronized keyworkd în fișierul dvs. getInstance() metoda. –  > Por dazito.
  • @Akayh Ați putea să explicați de ce Singleton nu este sigur pe Android? Este sigur doar nu este sigur pe activități sau nu este sigur nici pe aplicație? –  > Por Saba.
  • „Singleton în Android nu este sigur” – are nevoie de o referință și, în mod ideal, de o explicație. –  > Por noelicus.
Lazy

Sfat: Pentru a crea clasa singleton În Android Studio, faceți clic dreapta în proiect și deschideți meniul:

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

Comentarii

  • Nu mai este disponibil –  > Por Thecave3.
Rakesh

Este simplu, ca un java, Android suportă, de asemenea, singleton. –

Singleton este o parte a modelului de proiectare Gang of Four și este clasificat în cadrul modelelor de proiectare creativă.

-> Membru static: Acesta conține instanța clasei singleton.

-> Constructor privat: Acesta va împiedica pe oricine altcineva să instanțieze clasa Singleton.

-Metoda publică statică: Aceasta oferă punctul global de acces la obiectul Singleton și returnează instanța clasei care apelează clientul.

  1. crearea unei instanțe private
  2. creați un constructor privat
  3. utilizează getInstance() al clasei Singleton

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

while use singleton –

Logger.getInstance();

Comentarii

  • Cu ce diferă acest lucru de implementarea originală a singletonului de către utilizatorul postat? –  > Por IgorGanapolsky.
ashish.n

răspunsul sugerat de rakesh este grozav, dar încă cu unele discriptionSingleton în Android este același ca și Singleton în Java: Modelul de proiectare Singleton abordează toate aceste preocupări. Cu modelul de proiectare Singleton puteți:

1) Asigurați-vă că este creată o singură instanță a unei clase.

2) să oferiți un punct global de acces la obiect

3) Permiteți mai multe instanțe în viitor fără a afecta clienții unei clase singleton.

Un exemplu de bază de clasă Singleton:

public class MySingleton
{
    private static MySingleton _instance;

    private MySingleton()
    {

    }

    public static MySingleton getInstance()
    {
        if (_instance == null)
        {
            _instance = new MySingleton();
        }
        return _instance;
    }
}

Comentarii

  • Categoric, aceasta este cea mai bună abordare, deoarece a realizat un constructor leneș, cu alte cuvinte, este instanțiată doar atunci când getInstance() este apelat pentru prima dată. –  > Por Ângelo Polotto.
Adam

După cum a afirmat @Lazy în acest răspuns, puteți crea un singleton dintr-un șablon în Android Studio. Este demn de remarcat faptul că nu este nevoie să verificați dacă instanța este nulă, deoarece statica ourInstance este inițializată mai întâi. Prin urmare, implementarea clasei singleton creată de Android Studio este la fel de simplă ca următorul cod:

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

    public static MySingleton getInstance() {
        return ourInstance;
    }

    private MySingleton() {
    }
}

Comentarii

  • Aceasta este cea mai simplă și cea mai rapidă soluție. Dacă apelați getInstance() de multe ori într-o buclă, atunci celelalte răspunsuri cu o verificare pentru null vor fi semnificativ mai lente. –  > Por BitByteDog.
Dusan

Copiezi singletonul customVar într-un singletonVar variabilă și modificarea acelei variabile nu afectează valoarea originală din 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;

Comentarii

  • Nu ar fi mai sigur să faceți din customVar o variabilă statică privată și să creați metode de accesoriu pentru ea? –  > Por IgorGanapolsky.
jiahao

Am pus versiunea mea de Singleton mai jos:

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.");
    }
}

Rețineți că metoda initialize ar putea fi apelată în clasa principală(Splash), iar metoda getInstance ar putea fi apelată din alte clase. Acest lucru va rezolva problema atunci când clasa apelantă are nevoie de singleton, dar nu are contextul.

În cele din urmă, metoda hasBeenInitialized este utilizată pentru a verifica dacă clasa a fost inițializată. Acest lucru va evita ca diferite instanțe să aibă contexte diferite.

Comentarii

  • Android Studio va trata acest răspuns ca pe o problemă – scurgere de memorie – deoarece aveți un context setat în cadrul unei „instanțe” statice a unei alte clase. Acest model este acum inutil –  > Por narkis.
  • @narkis Interesant. Dacă acest lucru este adevărat, atunci când oamenii au instanța statică de Context în interiorul CustomApplication va genera, de asemenea, o scurgere de memorie. Ar trebui să ne încălziți pe toți despre asta 🙂 –  > Por jiahao.
nelimitat101

Cel mai curat și mai modern mod de a utiliza singletons în Android este doar să utilizați Dependency Injection numit Dagger 2. Aici aveți o explicație a domeniilor posibile pe care le puteți utiliza. Singleton este unul dintre aceste domenii de aplicare. Injectarea dependenței nu este atât de ușoară, dar trebuie să investiți puțin din timpul dumneavoastră pentru a o înțelege. De asemenea, facilitează testarea.