2016-02-12 75 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