2016-09-28 2 views
2

Например, если у меня есть эти куски кода:Зачем/когда использовать realm.beginTransaction? Поскольку существует executeTransaction и executeTransactionAsync

Realm realm = Realm.getDefaultInstance(); 

realm.beginTransaction(); 
mUser.setName("Roy"); 
realm.commitTransaction(); 

textView1.setText(mUser.getName()); 

Согласно документу, это говорит о том, что Exception будет пойман и данные не будут сохранены, если есть ошибка внутри транзакции. Итак, в приведенном выше коде, скажем, если что-то не так в mUser.setName("Roy"); или realm.commitTransaction();, там не будет сбоя, и код все равно будет продолжаться? Однако в этом случае cancelTransaction не вызывается. Что случится? Обновление: Похоже, приложение не будет разбиваться, но в следующий раз, если вы продолжите читать что-то из Realm, он потерпит крах и скажет вам, что Королевство заблокировано, потому что commitTransaction не вызывается.

Я просто не понимаю, в каких шансах вы будете использовать и commitTransaction, если существует риск возникновения ошибок. Есть alreay executeTransaction и executeTransactionAsync могут справиться с этим хорошо. Особенно с executeTransactionAsync, я думаю, что большинство из вас будет использовать executeTransactionAsync, так как оно имеет onSuccess и onError.

Для меня я могу думать только об одной причине: я хочу просто сделать простое обновление данных и по-прежнему использовать тот же поток. В этом случае я буду использовать:

try { 
    realm.executeTransaction(new Realm.Transaction() { 
     @Override 
     public void execute(Realm realm) { 
      mUser.setName("Roy"); 
     } 
    }); 
} catch (Exception e) { 
    Logger.e(TAG, "error", e); 
    Toast.makeText(getActivity(), R.string.error_occurred, Toast.LENGTH_SHORT).show(); 
    return; 
} 
+0

Еще одна вещь, которую @EpicPandaForce не упоминает в ответ, вызвав 'executeTransaction' в потоке петлителя (например, поток пользовательского интерфейса), изменит все запросы aync в этом потоке для синхронизации запросов. Поэтому, если вы используете синхронизирующие запросы в потоке пользовательского интерфейса, вам лучше использовать 'executeTransactionAsync' в потоке пользовательского интерфейса. – beeender

+1

@beeender Я не указывал, что потому что 'begin/commitTransaction()' также является синхронной транзакцией записи, которая также синхронизирует асинхронные запросы. – EpicPandaForce

ответ

3
realm.executeTransaction(new Realm.Transaction() { 
    @Override 
    public void execute(Realm realm) { 
     //... 
    } 
}); 

эквивалентно

realm.beginTransaction(); 
try { 
    //... 
    realm.commitTransaction(); 
} catch(Throwable e) { 
    if(realm.isInTransaction()) { 
     realm.cancelTransaction(); 
    } 
    throw e; 
} 

Итак, если вы спросите меня, begin/commit является подверженными ошибками, и вы не должны использовать его без его статей catch { cancel.. }.

Что касается не звонка cancelTransaction() в случае неудачи, я просто закончил с загадочными проблемами, которые прекратились, как только я начал звонить cancelTransaction(), но это было давно.

+0

Я могу освободить вас. Таким образом, похоже, что сбой произойдёт, если в транзакции произошла ошибка. Я до сих пор не знаю, кто будет использовать 'realm.executeTransaction' или' realm.beginTransaction() 'и' realm.commitTransaction() ', поскольку они не являются действительно аварийными ... – Arst

+0

Выполнение автоматически отменяет транзакцию. В этом и суть. – EpicPandaForce

1

Это, как я понимаю, что двусмысленность:

Как сказал EpicPandaForce в случае «BeginTransaction-CommitTransaction» вы можете поймать исключение и решить, что делать с ним, но в случае «executeTransaction» вы можете» t - вы не можете сказать выше уровня, что ошибка произошла.