我是否使用Singleton与Realm数据库正确?

时间:2016-06-11 22:03:10

标签: java android design-patterns singleton realm

我有一个应用程序,用户可以在其中创建/删除/编辑DialogFragment中的列表。在我的DialogFragments中使用这样的方法之前:MainActivtity.adapter.add(String name, String location, double price);

adapter是recyclerView的适配器对象。适配器的类具有我对recyclelerView中的项的创建/删除/编辑方法。如上所示,这就像我所理解的那样,也是一种叫做mehtods的可怕方式。

所以我选择将所有这些CRUD方法放在一个单独的类中,并像这样调用这些方法:Service.getInstance().add(...);

这是一种正确的方法吗?我能做得更好吗?

这就是我如何创建现在包含我的CRUD方法的单例类,而不是像以前一样将它们放在我的适配器类中。[/ p>

public class Service {

private static Realm realm;
private static Service service = new Service();

private Service() {
    realm = Realm.getInstance(App.getAppContex());
}

public static Service getInstance(){

    if(service == null){
        service = new Service();
    }
    return service;
}



   public void add(String name, String location, double price) {


    ShopListItem shopListItem = new ShopListItem();

    shopListItem.setName(name);
    shopListItem.setLocation(location);
    shopListItem.setPrice(price);
    shopListItem.setTimestamp(System.currentTimeMillis());
    shopListItem.setIsBought(0);

    realm.beginTransaction();
    realm.copyToRealm(shopListItem);
    realm.commitTransaction();
}


public void removeItem(int position, List<ShopListItem> shopListItems) {

    realm.beginTransaction();
    shopListItems.remove(position);
    realm.commitTransaction();
}

此类仅用于获取全局/应用程序上下文

public class App extends Application {


public static Application sApplication;

public static Application getsApplication(){
    return sApplication;
}

public static Context getAppContex(){

    return getsApplication();
}

@Override
public void onCreate() {
    super.onCreate();
    sApplication = this;
}
}

问题从此处更新:

以下是基于评论建议的新方法: 现在,每当我想在Realm数据库中进行CRUD操作时,我总是从我的realm对象的getDefaultInstance开始,并使用realm.close()完成;每个CRUD方法都会重现这个过程。

public class Service {

private Realm realm;
private static Service service = new Service();

private Service() {


}

public static Service getInstance(){

    if(service == null){
        service = new Service();
    }
    return service;
}

public void removeItem(int position, List<ShopListItem> shopListItems) {
    //new: realm = Realm.getDefaultInstance();

    realm = Realm.getDefaultInstance();
    realm.beginTransaction();
    shopListItems.remove(position);
    realm.commitTransaction();
    realm.close();
    //new: realm.close();
}

Realm配置现在按照Realm的建议移动到我的Application类。

public class App extends Application {


public static Application sApplication;

public static Application getsApplication(){
    return sApplication;
}

public static Context getAppContex(){

    return getsApplication();
}

@Override
public void onCreate() {
    super.onCreate();
    sApplication = this;
final RealmConfiguration realmConfiguration = new    RealmConfiguration.Builder(App.getAppContex()).build();
    realm.setDefaultConfiguration(realmConfiguration);
}
}

2 个答案:

答案 0 :(得分:0)

你根本不应该使用单身的单身。因为领域是面向线程的。你应该打开新的默认实例并关闭它。

或者您可以使用threadId与realm对象的映射。其中线程是弱引用。

答案 1 :(得分:0)

Realm表示当线程到达执行结束时(或不再需要本地实例)时需要关闭的线程限制的本地实例。

从Realm检索的任何对象都绑定到Realm的生命周期,这意味着一旦每个Realm实例在给定线程上关闭,它们就会失效(对getInstance()的调用会增加引用计数,close()减少它。)

因此,创建static Realm realm很可能只能在UI线程上访问。

要将Realm用作单例(并且能够以可靠的方式创建/检索线程本地Realm实例),您需要this之类的内容:

@Singleton
public class RealmManager {
    private final ThreadLocal<Realm> localRealms = new ThreadLocal<>();

    @Inject
    RealmManager() {
    }

    /**
     * Opens a reference-counted local Realm instance.
     *
     * @return the open Realm instance
     */
    public Realm openLocalInstance() {
        checkDefaultConfiguration();
        Realm realm = Realm.getDefaultInstance();
        if(localRealms.get() == null) {
            localRealms.set(realm);
        }
        return realm;
    }

    /**
     * Returns the local Realm instance without adding to the reference count.
     *
     * @return the local Realm instance
     * @throws IllegalStateException when no Realm is open
     */
    public Realm getLocalInstance() {
        Realm realm = localRealms.get();
        if(realm == null) {
            throw new IllegalStateException(
                    "No open Realms were found on this thread.");
        }
        return realm;
    }

    /**
     * Closes local Realm instance, decrementing the reference count.
     *
     * @throws IllegalStateException if there is no open Realm.
     */
    public void closeLocalInstance() {
        checkDefaultConfiguration();
        Realm realm = localRealms.get();
        if(realm == null) {
            throw new IllegalStateException(
                    "Cannot close a Realm that is not open.");
        }
        realm.close();
        // noinspection ConstantConditions
        if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
            localRealms.set(null);
        }
    }

    private void checkDefaultConfiguration() {
        if(Realm.getDefaultConfiguration() == null) {
            throw new IllegalStateException("No default configuration is set.");
        }
    }
}

这样,您可以在执行的开始/结束时打开/关闭Realm,但仍然可以获取Realm而不必将其作为方法参数传递。

private void doSomething() {
    Realm realm = realmManager.getLocalInstance();

或者

    realmManager.openLocalInstance();
    // .. do whatever
    realmManager.closeLocalInstance();