我正在尝试使用单例(PhotoStorage)来提供Photo对象的arrayList,但似乎PhotoStorage实例的行为不像单例(两个实例)。
我正在使用匕首将这个单例注入一个名为PhotoInteractor的类中。到目前为止,objectGraph似乎是A-OK。 在viewpager中的三个片段中使用相同的PhotoInteractor实例。这些片段都在运行时实例化:
RecentFragment:
HistoryFragment:
注意PhotoInteractor的实例@ 4067对于两个片段是如何相同的。
此外:
当我从RecentFragment单击照片对象(网格图像)时,将调用PhotoStorage.addPhoto(url)方法。这将照片对象正确添加到photoStorage实例数组(4094)。那太好了。
问题:
当我关闭应用程序时, PhotoStorage.savePhotosToFile 方法会将此arrayList对象序列化为文件系统上的JSON。
从同一个PhotoInteractor实例调用以下方法:
@Override
public void savePhotos(){
photoStorage.get(mAppContext).savePhotosToFile();
}
当我调试应用程序时, PhotoStorage.get 方法已经有一个单例实例,但看起来是第二个实例!
//Singleton enforcement
public static PhotoStorage get(Context c){
if(sPhotoStorage == null){
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
return sPhotoStorage;
}
这意味着照片的ArrayList将始终为空,因为它是PhotoStorage的新实例。我不确定它是从哪里实例化的。
编辑 - 添加了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;
}
}
}
答案 0 :(得分:0)
您没有以正确的方式执行Singletton pattern,
Singleton设计模式解决了所有这些问题。使用Singleton设计模式,您可以:
确保只创建一个类的一个实例
提供对象的全局访问点
在您的情况下,我们看不到PhotoStorage
类,但此调用来自实例,Singletton pattern不允许的内容:
photoStorage.get(mAppContext).savePhotosToFile();
//↑ instance call WRONG!!
此行有效,但由于get
方法static
不是Karakuri指向的良好做法,因此也违反了Singletton pattern定义。
public static PhotoStorage get(Context c){
<强>解强>
要使photoStorage.get()
无效并创建正确的Singletton pattern,您必须:
getInstance()
方法静态(此处为PhotoStorage
)getInstance()
:
class PhotoStorage {
// hidding default constructor
private PhotoStorage () {};
// creating your own constructor but 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;
}
}
然后你可以从类范围允许的任何地方进行静态调用:
@Override
public void savePhotos(){
PhotoStorage.get(mAppContext).savePhotosToFile();
//↑ static call CORRECT!!
}
更新:
如果您的应用有多个主题且单例getInstance请求可能重叠,则可以申请double check syncronized singletton pattern:
//Singleton enforcement
public synchronized static PhotoStorage get(Context c){
if(sPhotoStorage == null){
synchronized(PhotoStorage.class) {
if(sPhotoStorage == null) {
sPhotoStorage = new PhotoStorage(c.getApplicationContext());
}
}
}
}