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:

historyfragment:

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 (herephotostorage)
- 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
Post a Comment