2017-06-02 71 views
0

我有管理的倍數片段和嵌套片段,這樣的活動:如何管理領域實例?

活動 - > 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

回答

2

該文檔說你應該打開/關閉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