java - Singleton returning two instances -


i'm trying use singleton (photostorage) provide arraylist of photo objects, seems photostorage instance not behaving singleton (two instances).

i using dagger inject singleton class named photointeractor. objectgraph seems a-ok point. same photointeractor instance used in 3 fragments in viewpager. these fragments instantiated @ runtime:

recentfragment:

recent_fragment

historyfragment:

history_frag

notice how instance @4067 of photointeractor same both fragments.

also:

  • mappcontext@4093: same
  • photostorage@4094: same

when click photo object (grid image) recentfragment, photostorage.addphoto(url) method called. correctly adds photo object photostorage instance array (4094). ok.

problem:

when close applicaton, intended photostorage.savephotostofile method serialzes arraylist object json on filesystem.

the following method called same photointeractor instance:

@override public void savephotos(){     photostorage.get(mappcontext).savephotostofile(); } 

when debug application, photostorage.get method has singleton instance, appears 2nd instance!

//singleton enforcement public static photostorage get(context c){     if(sphotostorage == null){         sphotostorage = new photostorage(c.getapplicationcontext());     }     return sphotostorage; } 

this means arraylist of photos empty since new instance of photostorage. i’m not sure instantiating from.

edit - added photostorage.class:

public class photostorage{     private arraylist<photo> mphotos;     private photojsoner mserializer;     private static photostorage sphotostorage;     private static context mappcontext;     private static final string photos_database = "photos.json";     public static final string tag = photostorage.class.getsimplename();  public photostorage(context appcontext){     mserializer = new photojsoner(appcontext, photos_database);     try{         mphotos = mserializer.loadphotos();     }catch(exception e){         mphotos = new arraylist<photo>();     } }  //singleton enforcement public static photostorage get(context c){     if(sphotostorage == null){         sphotostorage = new photostorage(c.getapplicationcontext());     }     return sphotostorage; }  public arraylist<photo> getphotos(){     return mphotos; }  public photo getphoto(string url){     for(photo p: mphotos){         if(p.geturl() == url)             return p;     }     return null; }  public void deletephoto(string url){     log.i(tag, "deleted photo");     mphotos.remove(url); }  public void addphoto(photo photo){     log.i(tag, "added photo");     mphotos.add(photo); }  public boolean savephotostofile(){     try{         mserializer.savephotos(mphotos);         return true;     }catch (exception e){         return false;     } } 

}

you not executing singletton pattern in correct way,

the singleton design pattern addresses of these concerns. singleton design pattern can:
ensure 1 instance of class created
provide global point of access object

in case, don't see photostorage class call comes instance, not allowed singletton pattern:

photostorage.get(mappcontext).savephotostofile(); //↑ instance call wrong!! 

this line works, get method static not practice karakuri pointed , breaks singletton pattern definition.

public static photostorage get(context c){ 

solution
make photostorage.get() invalid , create correct singletton pattern must:

  • declare getinstance() method static in class (here photostorage)
  • hide default constructor avoid instances of class
  • create private constructors if necessary
  • call getinstance() in static way:

class photostorage {      // hidding default constructor     private photostorage () {};      // creating own constructor private!!!     private photostorage(context appcontext){         mserializer = new photojsoner(appcontext, photos_database);         try{             mphotos = mserializer.loadphotos();         }catch(exception e){             mphotos = new arraylist<photo>();         }     }      //singleton enforcement     public synchronized static photostorage get(context c){         if(sphotostorage == null){             sphotostorage = new photostorage(c.getapplicationcontext());         }         return sphotostorage;     } } 

then can make static call everywhere class scope allows:

@override public void savephotos(){       photostorage.get(mappcontext).savephotostofile();     //↑ static call correct!! } 

update:
if app have several threads , singleton getinstance requests may overlapp, there double check syncronized singletton pattern can apply:

//singleton enforcement public synchronized static photostorage get(context c){     if(sphotostorage == null){         synchronized(photostorage.class) {             if(sphotostorage == null) {                 sphotostorage = new photostorage(c.getapplicationcontext());             }         }     } } 

Comments

Popular posts from this blog

html - Firefox flex bug applied to buttons? -

html - Missing border-right in select on Firefox -

c# - two queries in same method -