2016-02-12 64 views
2

我正在使用領域和碎片的應用程序。領域設置需要加密,並且要刪除領域db,並在用戶註銷時生成新密鑰。可靠地關閉領域(片段)

爲了執行註銷操作,我在沒有任何碎片的任務頂部啓動一項新的活動,並啓動一個處理所有註銷清理的IntentService。

我遇到的問題是,我似乎無法可靠地讓我的碎片放開他們的領域實例,讓領域被刪除。在onStop/onPause/onDestroy中關閉片段領域時,總會有一兩個片段似乎需要花時間從Android的片段緩存中關閉/清除。

我已將我的視圖傳呼機切換到使用FragmentStatePagerAdapers,這減少了打開的片段數量,並有所幫助。

因此,在我的IntentService中,我採取了循環Realm.delete(),直到它成功 - 它最終似乎做到了。有時等待時間很短,有時是幾分鐘。這是非常可變的。

我以前想過的事情是用事件觸發事件(使用EventBus),這些片段監聽這些事件會導致它們關閉它們的領域實例。

但有沒有更好的方式讓我的碎片關閉/及時關閉他們的領域實例(除了不使用碎片)?

RealmFragment.java:

import android.support.v4.app.Fragment; 
import android.util.Log; 

import io.realm.Realm; 

public class RealmFragment extends Fragment { 
    private Realm realm = null; 
    private final Object realmLock = new Object(); 

    public Realm getRealm() { 
     if (realm == null || realm.isClosed()) { 
      synchronized (realmLock) { 
       if (realm == null || realm.isClosed()) { 
        realm = Realm.getDefaultInstance(); 
       } 
      } 
     } 
     return realm; 
    } 

    @Override 
    public void onPause() { 
     super.onPause(); 
     closeRealm(); 
    } 

    @Override 
    public void onStop() { 
     super.onStop(); 
     closeRealm(); 
    } 

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

    private void closeRealm() { 
     if (realm != null && !realm.isClosed()) { 
      synchronized (realmLock) { 
       if (realm != null && !realm.isClosed()) { 
        try { 
         realm.close(); 
        } 
        catch (Exception e) { 
         Log.e("REALM","Couldn't close realm."); 
        } 
        realm = null; 
       } 
      } 
     } 
    } 

} 

登錄屏幕啓動:

case R.id.logout: { 
     AlertDialog alertDialog = new AlertDialog.Builder(this) 
     .setTitle(R.string.confirm_sign_out) 
     .setMessage(R.string.sign_out_description) 
     .setPositiveButton(
      android.R.string.ok, 
      new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       // close this activity's realm before launching sign out. 
       MyActivity.closeRealm(); 
       Intent signOutIntent = new Intent(MyActivity.this, SignOutActivity.class); 
       signOutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); 
       // this starts the logout process. It begins with removing an Android 
       // system account, and a receiver that listens for that to complete. When 
       // the account removal is complete, then we can continue with the rest of 
       // the logout process. 
       Actions.logoutAccount(getApplicationContext()); 
       startActivity(signOutIntent); 
       // I could call this before calling startActivity()? 
       MyActivity.finish(); 
      } 
     }) 
    .setNegativeButton(
     android.R.string.cancel, 
     new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int which) { 
       dialog.dismiss(); 
      } 
     }) 
    .setCancelable(true) 
    .create(); 
    alertDialog.show(); 
    break; 
    } 
+1

我個人建議在保留片段的構造函數或onCreate()中打開一個Realm實例,然後將該片段綁定到您的Activity並關閉onDestroy()中的領域。這樣,只會有一個共享Realm,並且它將被綁定到沒有緩存的活動生命週期。你會從該保留的片段中將該Realm引用到你的Activity中,而你的其他片段將從Activity中獲得它們的Realm引用。 – EpicPandaForce

+1

片段生命週期是非常困難的。你有沒有試過尋找http://developer.android.com/reference/android/app/Fragment.html#setUserVisibleHint(boolean)或haps控制你的任務堆棧,所以你打開你的登錄/註銷時強制關閉所有活動屏幕? –

+0

@EpicPandaForce - 領域實例是懶惰地獲取的,而不是onCreate() - 我有太多問題,實例變得無效。我將添加上面使用的代碼。 – Mark

回答

0

片段生命週期確實是問題。感謝上面評論中@ChrisitianMelchior提供的提示,我能夠解決此問題。關鍵是要設置下列標誌上的活動,像這樣:

signOutIntent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK );

這導致了之前的活動(-ies)及其碎片拿到關機,這解鎖的境界。

+0

呃,這工作得很好,似乎是好幾個小時。我只是試了一遍,仍然陷入了同樣的問題。這不是一個完整的解決方案。 – Mark

+0

另一種解決方案可能是爲每個用戶創建一個Realm?那麼你可以用更受控制的方式刪除舊的Realms,例如啓動應用程序時? –

+1

我創建了一個RealmMonitor單例類,它用RealmMonitor.getInstance(Object o)和RealmMonitor.close(Object o,Realm realm)代理我所有對Realm.getInstance()和realm.close()的調用; 這允許我跟蹤打開和關閉。正如預期的那樣,在關閉碎片時存在延遲,但意想不到的是關閉活動似乎有延遲。 我有一個啓動器/控制器活動,它根據某些條件委託其他活動。我已經在其中重寫了startActivity(): – Mark