辛格尔顿返回两个实例 [英] Singleton returning two instances

查看:126
本文介绍了辛格尔顿返回两个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用一个单(PhotoStorage)提供照片对象的ArrayList,但它似乎PhotoStorage实例未表现为一个单独(两个实例)。

I'm trying to use a singleton (PhotoStorage) to provide an arrayList of Photo objects, but it seems that the PhotoStorage instance is not behaving as a singleton (two instances).

我使用匕首注入此singleton到一个名为PhotoInteractor类。该objectGraph似乎都OK了这一点。
相同PhotoInteractor实例在三个片段用于在viewpager。这些片段都被实例化在运行时:

I am using dagger to inject this singleton into a class named PhotoInteractor. The objectGraph seems A-OK up to this point. The same PhotoInteractor instance is used in three fragments in a viewpager. These fragments are all instantiated at runtime:

RecentFragment:

HistoryFragment:

注意实例@的PhotoInteractor 4067是如何成为两个片段是相同的。

Notice how the instance @4067 of the PhotoInteractor is the same for both fragments.

还有:


  • mAppContext @ 4093:相同

  • photoStorage @ 4094:相同

当我点击从RecentFragment照片对象(网格图),该PhotoStorage.addPhoto(URL)方法被调用。这正确添加照片对象的实例photoStorage阵列(4094)。这一点是确定。

When I click a photo object (grid image) from RecentFragment, the PhotoStorage.addPhoto(url) method is called. This correctly adds the photo object to the photoStorage instance array (4094). That much is OK.

问题:

当我关闭一个应用,其意图是在 PhotoStorage.savePhotosToFile 方式serialzes这个ArrayList对象成JSON上的文件系统。

When I close the applicaton, it is intended that the PhotoStorage.savePhotosToFile method serialzes this arrayList object into JSON on the filesystem.

下面的方法是从同一PhotoInteractor实例调用

The following method is called from the same PhotoInteractor instance:

@Override
public void savePhotos(){
    photoStorage.get(mAppContext).savePhotosToFile();
}

当我调试应用程序,在 PhotoStorage.get 方式已经有一个单实例,但是这似乎是一个第二个实例!

When I debug the application, the PhotoStorage.get method already has a singleton instance, but what appears to be a 2nd instance!

//Singleton enforcement
public static PhotoStorage get(Context c){
    if(sPhotoStorage == null){
        sPhotoStorage = new PhotoStorage(c.getApplicationContext());
    }
    return sPhotoStorage;
}

这意味着,照片该ArrayList永远是空的,因为它是PhotoStorage的新实例。我不知道它是从哪里实例化本身。

This means that the ArrayList of photos will always be empty since it is a new instance of PhotoStorage. I’m not sure where it is instantiating itself from.

编辑 - 添加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;
    }
}

}

推荐答案

您没有执行 Singletton模式以正确的方式,

You are not executing Singletton pattern in the correct way,

Singleton设计模式解决了所有这些问题。随着Singleton设计模式,您可以:结果
  确保只有一个类的实例被创建结果
  提供一个全局访问点的对象

The Singleton design pattern addresses all of these concerns. With the Singleton design pattern you can:
Ensure that only one instance of a class is created
Provide a global point of access to the object

在你的情况,我们没有看到 PhotoStorage 类,但这一呼吁源于一个实例,什么是不的 Singletton模式

In your case, we don't see PhotoStorage class but this call comes from an instance, what is not allowed by Singletton pattern:

photoStorage.get(mAppContext).savePhotosToFile();
//↑ instance call WRONG!!

这行工作,但作为你的 GET 方法静态不是一个好的做法,因为的Karakuri 尖,也打破了的 Singletton模式定义。

This line works, but as your get method is static is not a good practice as Karakuri pointed and also breaks the Singletton pattern definition.

public static PhotoStorage get(Context c){

SOLUTION 结果
为了让 photoStorage.get()无效并创建一个正确的 Singletton模式你必须:

SOLUTION
To make photoStorage.get() invalid and create a correct Singletton pattern you must:


  • 声明的getInstance()方法在类的静态(这里 PhotoStorage

  • 隐藏默认的构造函数,以避免类的实例

  • 创建私有构造函数如果有必要

  • 通话的getInstance()在一个静态的方式:

  • declare the getInstance() method static in the class (here PhotoStorage)
  • hide default constructor to avoid instances of the class
  • create private constructors if necessary
  • call getInstance() it in a static way:

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

然后你就可以静态调用来自世界各地类范围内允许:

Then you can make static call from everywhere the class scope allows:

@Override
public void savePhotos(){
      PhotoStorage.get(mAppContext).savePhotosToFile();
    //↑ static call CORRECT!!
}

更新:结果,如果你的应用程序有多个线程和单身的getInstance请求可能overlapp,有一个的仔细检查syncronized singletton模式你可以申请?

UPDATE:
if your app have several threads and singleton getInstance requests may overlapp, there is a double check syncronized singletton pattern you 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());
            }
        }
    }
}

这篇关于辛格尔顿返回两个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆