2017-06-02 17 views
0

私はそのように、倍数のフラグメントおよびネストされたフラグメントを管理する活性を有する:レルムインスタンスの管理方法は?

活動 - > RootFragment1 - > NestedFragment1、NestedFragment2
- > RootFragment2 - > NestedFragment3、NestedFragment4 ...

私が使用してレルムインスタンスを取得し、ONSTARTでネストされた各フラグメントにそれを閉じ、onStop方法が、時々私は、この例外を満たす:

致命的な例外:java.lang.IllegalStateException:このレルムインスタンス はすでに閉じられており、使用できなくなっています。

Realmインスタンスを取得して閉じる方法はありますか?私の場合、アクティビティでインスタンスを取得し、それをフラグメントに渡す必要がありますか?

+0

個人的にはフラグメントのonCreate/onDestroyに移動することを考えています – EpicPandaForce

+0

**実際に**私はRealmインスタンスをUIスレッド用に開いて保持していますが、 :Dこれは、すべてのこのトリッキーなライフサイクルのフェナニガンを避ける – EpicPandaForce

+0

あなたのソリューションのサンプルがありますか? – CuirMoustachu

答えて

2

レルムのオープン/クローズはonCreateView()/onDestroyView()であると言われていますが、私の経験ではフラグメントライフサイクルが異常に不安定であるため、2つの方法があります。 と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); 
    } 
} 

はその後の断片に、あなたは

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

を行うことができますし、ビューに、あなたは

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

2.を行うことができます)保持を使用してUIスレッドに対してグローバルレルムのライフサイクルを管理しますライフサイクルリスナ/アクティビティ参照カウンタとしてのフラグメント。

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

に伴い

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

これは、UIスレッドためRealmManager.getRealm()を呼び出すことができますし、そのライフサイクルを保持しているフラグメントによって管理されています。

+0

バックグラウンドスレッドを開始しないサービスでRealmManager.getRealm()を使用するのは安全ですか? – CuirMoustachu

+0

えええええええええええええええええええええええええええええええんがんは、私のケースでは、活動が閉じられていて、活動が活動よりも古くなっているので、私は投票しません。あなたはおそらくそこで自分自身を開いて閉じなければなりません。 – EpicPandaForce

+0

これは私が思ったことを確認して、すべてのケースでonDestroyが呼び出されているかどうか、またそこでインスタンスの数を減らすのが安全かどうかも疑問に思っています。 – CuirMoustachu

関連する問題