如何管理领域实例?

问题描述:

我有管理的倍数片段和嵌套片段,这样的活动:如何管理领域实例?

活动 - > RootFragment1 - > NestedFragment1,NestedFragment2
- > RootFragment2 - > NestedFragment3,NestedFragment4 ...

我使用得到一个领域实例,并在在onStart每个分片嵌套关闭它,方法的onStop但有时我遇到此异常:

致命异常:java.lang.IllegalStateException:这个领域实例 已经关闭,使其无法使用。

是否有推荐的方法来获得Realm实例并关闭它?在我的情况下,我应该在Activity中获得一个实例并将其传递给我的碎片?

+0

我个人会考虑将它们移动到片段的onCreate/onDestroy上 – EpicPandaForce

+0

尽管**实际上**我为UI线程保留一个Realm实例并使用保留的片段进行管理,但这有点棘手:D它可以避免所有这些棘手的生命周期shenanigan – EpicPandaForce

+0

您是否有解决方案的样本? – CuirMoustachu

该文档说你应该打开/关闭Realm在onCreateView()/onDestroyView(),但以我的经验来说,片段生命周期异常不稳定,所以我可以告诉你另外两种方法。

1.)打开/关闭Activity.onCreate()Activity.onDestroy()中的领域,然后使用getSystemService()将它共享到片段(甚至在视图层次结构中!)。

public class MyActivity extends AppCompatActivity { 
    Realm realm; 

    @Override 
    protected void onCreate(Bundle bundle) { 
     // ... 
     realm = Realm.getDefaultInstance(); 
    } 

    @Override 
    protected void onDestroy() { 
     realm.close(); 
     realm = null; 
     // ... 
    } 

    // ----------------------------- 
    private static final String REALM_TAG = "__REALM__"; 

    public static Realm getRealm(Context context) { 
     // noinspection ResourceType 
     return (Realm)context.getSystemService(REALM_TAG); 
    } 

    @Override 
    public Object getSystemService(@NonNull String name) { 
     if(REALM_TAG.equals(name)) { 
      return realm; 
     } 
     return super.getSystemService(name); 
    } 
} 

然后在片段您可以在UI线程做

Realm realm = MyActivity.getRealm(getActivity()); 

而且在视图中,你可以做

Realm realm = MyActivity.getRealm(getContext()); 

2)管理领域全球生命周期使用保存片段作为生命周期监听器/活动引用计数器。

/** 
* Created by Zhuinden on 2016.08.16.. 
*/ 
public class RealmManager { 
    private static final String TAG = "RealmManager"; 

    static Realm realm; 

    static RealmConfiguration realmConfiguration; 

    public static void init(Context context) { 
     Realm.init(context); 
    } 

    public static void initializeRealmConfig(Context appContext) { 
     if(realmConfiguration == null) { 
      Log.d(TAG, "Initializing Realm configuration."); 
      setRealmConfiguration(new RealmConfiguration.Builder(appContext).initialData(new RealmInitialData()) 
        .deleteRealmIfMigrationNeeded() 
        .inMemory() 
        .build()); 
     } 
    } 

    public static void setRealmConfiguration(RealmConfiguration realmConfiguration) { 
     RealmManager.realmConfiguration = realmConfiguration; 
     Realm.setDefaultConfiguration(realmConfiguration); 
    } 

    private static int activityCount = 0; 

    public static Realm getRealm() { // use on UI thread only! 
     return realm; 
    } 

    public static void incrementCount() { 
     if(activityCount == 0) { 
      if(realm != null) { 
       if(!realm.isClosed()) { 
        Log.w(TAG, "Unexpected open Realm found."); 
        realm.close(); 
       } 
      } 
      Log.d(TAG, "Incrementing Activity Count [0]: opening Realm."); 
      realm = Realm.getDefaultInstance(); 
     } 
     activityCount++; 
     Log.d(TAG, "Increment: Count [" + activityCount + "]"); 
    } 

    public static void decrementCount() { 
     activityCount--; 
     Log.d(TAG, "Decrement: Count [" + activityCount + "]"); 
     if(activityCount <= 0) { 
      Log.d(TAG, "Decrementing Activity Count: closing Realm."); 
      activityCount = 0; 
      realm.close(); 
      if(Realm.compactRealm(realmConfiguration)) { 
       Log.d(TAG, "Realm compacted successfully."); 
      } 
      realm = null; 
     } 
    } 
} 

在结合

public class RealmScopeListener 
     extends Fragment { 
    public RealmScopeListener() { 
     setRetainInstance(true); 
     RealmManager.incrementCount(); 
    } 

    @Override 
    public void onDestroy() { 
     RealmManager.decrementCount(); 
     super.onDestroy(); 
    } 
} 

而且

/** 
* Created by Zhuinden on 2016.09.04.. 
*/ 
public class RealmActivity extends AppCompatActivity { 
    protected Realm realm; 

    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) { 
     RealmManager.init(this); 
     RealmManager.initializeRealmConfig(getApplicationContext()); 

     super.onCreate(savedInstanceState); 
     RealmScopeListener realmScopeListener = (RealmScopeListener)getSupportFragmentManager().findFragmentByTag("SCOPE_LISTENER"); 
     if(realmScopeListener == null) { 
      realmScopeListener = new RealmScopeListener(); 
      getSupportFragmentManager().beginTransaction().add(realmScopeListener, "SCOPE_LISTENER").commit(); 
     } 
     realm = RealmManager.getRealm(); 
    } 
} 

这使您可以拨打RealmManager.getRealm()的UI线程,它的生命周期被保留碎片管理。

+0

在不启动后台线程的服务中使用RealmManager.getRealm()是否安全? – CuirMoustachu

+0

嗯....考虑到Realm实例在我的情况下是关闭的,当活动关闭和服务超出活动时,我会投反对票。你应该在那里打开并关闭领域。 – EpicPandaForce

+0

好吧,这证实了我的想法,我也想知道是否在每种情况下调用onDestroy,并且在那里减少领域实例数是否安全? – CuirMoustachu