Search in sources :

Example 1 with RealmNotifier

use of io.realm.internal.RealmNotifier in project realm-java by realm.

the class DynamicRealm method executeTransactionAsync.

/**
 * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess and OnError callbacks.
 *
 * @param transaction {@link Transaction} to execute.
 * @param onSuccess callback invoked when the transaction succeeds.
 * @param onError callback invoked when the transaction fails.
 * @return a {@link RealmAsyncTask} representing a cancellable task.
 * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from
 * another thread.
 */
public RealmAsyncTask executeTransactionAsync(final Transaction transaction, @Nullable final Transaction.OnSuccess onSuccess, @Nullable final Transaction.OnError onError) {
    checkIfValid();
    // noinspection ConstantConditions
    if (transaction == null) {
        throw new IllegalArgumentException("Transaction should not be null");
    }
    if (isFrozen()) {
        throw new IllegalStateException("Write transactions on a frozen Realm is not allowed.");
    }
    // Avoid to call canDeliverNotification() in bg thread.
    final boolean canDeliverNotification = sharedRealm.capabilities.canDeliverNotification();
    // the results.
    if ((onSuccess != null || onError != null)) {
        sharedRealm.capabilities.checkCanDeliverNotification("Callback cannot be delivered on current thread.");
    }
    // We need to use the same configuration to open a background OsSharedRealm (i.e Realm)
    // to perform the transaction
    final RealmConfiguration realmConfiguration = getConfiguration();
    // We need to deliver the callback even if the Realm is closed. So acquire a reference to the notifier here.
    final RealmNotifier realmNotifier = sharedRealm.realmNotifier;
    final Future<?> pendingTransaction = asyncTaskExecutor.submitTransaction(new Runnable() {

        @Override
        public void run() {
            if (Thread.currentThread().isInterrupted()) {
                return;
            }
            OsSharedRealm.VersionID versionID = null;
            Throwable exception = null;
            final DynamicRealm bgRealm = DynamicRealm.getInstance(realmConfiguration);
            bgRealm.beginTransaction();
            try {
                transaction.execute(bgRealm);
                if (Thread.currentThread().isInterrupted()) {
                    return;
                }
                bgRealm.commitTransaction();
                // The bgRealm needs to be closed before post event to caller's handler to avoid concurrency
                // problem. This is currently guaranteed by posting callbacks later below.
                versionID = bgRealm.sharedRealm.getVersionID();
            } catch (final Throwable e) {
                exception = e;
            } finally {
                try {
                    if (bgRealm.isInTransaction()) {
                        bgRealm.cancelTransaction();
                    }
                } finally {
                    bgRealm.close();
                }
            }
            final Throwable backgroundException = exception;
            final OsSharedRealm.VersionID backgroundVersionID = versionID;
            // Cannot be interrupted anymore.
            if (canDeliverNotification) {
                if (backgroundVersionID != null && onSuccess != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (isClosed()) {
                                // The caller Realm is closed. Just call the onSuccess. Since the new created Realm
                                // cannot be behind the background one.
                                onSuccess.onSuccess();
                                return;
                            }
                            if (sharedRealm.getVersionID().compareTo(backgroundVersionID) < 0) {
                                sharedRealm.realmNotifier.addTransactionCallback(new Runnable() {

                                    @Override
                                    public void run() {
                                        onSuccess.onSuccess();
                                    }
                                });
                            } else {
                                onSuccess.onSuccess();
                            }
                        }
                    });
                } else if (backgroundException != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (onError != null) {
                                onError.onError(backgroundException);
                            } else {
                                throw new RealmException("Async transaction failed", backgroundException);
                            }
                        }
                    });
                }
            } else {
                if (backgroundException != null) {
                    // Throw in the worker thread since the caller thread cannot get notifications.
                    throw new RealmException("Async transaction failed", backgroundException);
                }
            }
        }
    });
    return new RealmAsyncTaskImpl(pendingTransaction, asyncTaskExecutor);
}
Also used : RealmAsyncTaskImpl(io.realm.internal.async.RealmAsyncTaskImpl) RealmException(io.realm.exceptions.RealmException) RealmNotifier(io.realm.internal.RealmNotifier)

Example 2 with RealmNotifier

use of io.realm.internal.RealmNotifier in project realm-java by realm.

the class RealmResultTaskImpl method getAsync.

@Override
public void getAsync(App.Callback<T> callback) {
    Util.checkNull(callback, "callback");
    Util.checkLooperThread("RealmResultTaskImpl can only run on looper threads.");
    RealmNotifier handler = new AndroidRealmNotifier(null, new AndroidCapabilities());
    pendingTask = service.submit(new Runnable() {

        @Override
        public void run() {
            try {
                postSuccess(handler, executor.run(), callback);
            } catch (AppException e) {
                postError(handler, e, callback);
            } catch (Throwable e) {
                postError(handler, new AppException(ErrorCode.UNKNOWN, "Unexpected error", e), callback);
            }
        }
    });
}
Also used : AppException(io.realm.mongodb.AppException) AndroidRealmNotifier(io.realm.internal.android.AndroidRealmNotifier) RealmNotifier(io.realm.internal.RealmNotifier) AndroidRealmNotifier(io.realm.internal.android.AndroidRealmNotifier) AndroidCapabilities(io.realm.internal.android.AndroidCapabilities)

Example 3 with RealmNotifier

use of io.realm.internal.RealmNotifier in project realm-java by realm.

the class Realm method executeTransactionAsync.

/**
 * Similar to {@link #executeTransactionAsync(Transaction)}, but also accepts an OnSuccess and OnError callbacks.
 *
 * @param transaction {@link io.realm.Realm.Transaction} to execute.
 * @param onSuccess callback invoked when the transaction succeeds.
 * @param onError callback invoked when the transaction fails.
 * @return a {@link RealmAsyncTask} representing a cancellable task.
 * @throws IllegalArgumentException if the {@code transaction} is {@code null}, or if the realm is opened from
 * another thread.
 */
public RealmAsyncTask executeTransactionAsync(final Transaction transaction, @Nullable final Realm.Transaction.OnSuccess onSuccess, @Nullable final Realm.Transaction.OnError onError) {
    checkIfValid();
    // noinspection ConstantConditions
    if (transaction == null) {
        throw new IllegalArgumentException("Transaction should not be null");
    }
    if (isFrozen()) {
        throw new IllegalStateException("Write transactions on a frozen Realm is not allowed.");
    }
    // Avoid to call canDeliverNotification() in bg thread.
    final boolean canDeliverNotification = sharedRealm.capabilities.canDeliverNotification();
    // the results.
    if ((onSuccess != null || onError != null)) {
        sharedRealm.capabilities.checkCanDeliverNotification("Callback cannot be delivered on current thread.");
    }
    // We need to use the same configuration to open a background OsSharedRealm (i.e Realm)
    // to perform the transaction
    final RealmConfiguration realmConfiguration = getConfiguration();
    // We need to deliver the callback even if the Realm is closed. So acquire a reference to the notifier here.
    final RealmNotifier realmNotifier = sharedRealm.realmNotifier;
    final Future<?> pendingTransaction = asyncTaskExecutor.submitTransaction(new Runnable() {

        @Override
        public void run() {
            if (Thread.currentThread().isInterrupted()) {
                return;
            }
            OsSharedRealm.VersionID versionID = null;
            Throwable exception = null;
            final Realm bgRealm = Realm.getInstance(realmConfiguration);
            bgRealm.beginTransaction();
            try {
                transaction.execute(bgRealm);
                if (Thread.currentThread().isInterrupted()) {
                    return;
                }
                bgRealm.commitTransaction();
                // The bgRealm needs to be closed before post event to caller's handler to avoid concurrency
                // problem. This is currently guaranteed by posting callbacks later below.
                versionID = bgRealm.sharedRealm.getVersionID();
            } catch (final Throwable e) {
                exception = e;
            } finally {
                try {
                    if (bgRealm.isInTransaction()) {
                        bgRealm.cancelTransaction();
                    }
                } finally {
                    bgRealm.close();
                }
            }
            final Throwable backgroundException = exception;
            final OsSharedRealm.VersionID backgroundVersionID = versionID;
            // Cannot be interrupted anymore.
            if (canDeliverNotification) {
                if (backgroundVersionID != null && onSuccess != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (isClosed()) {
                                // The caller Realm is closed. Just call the onSuccess. Since the new created Realm
                                // cannot be behind the background one.
                                onSuccess.onSuccess();
                                return;
                            }
                            if (sharedRealm.getVersionID().compareTo(backgroundVersionID) < 0) {
                                sharedRealm.realmNotifier.addTransactionCallback(new Runnable() {

                                    @Override
                                    public void run() {
                                        onSuccess.onSuccess();
                                    }
                                });
                            } else {
                                onSuccess.onSuccess();
                            }
                        }
                    });
                } else if (backgroundException != null) {
                    realmNotifier.post(new Runnable() {

                        @Override
                        public void run() {
                            if (onError != null) {
                                onError.onError(backgroundException);
                            } else {
                                throw new RealmException("Async transaction failed", backgroundException);
                            }
                        }
                    });
                }
            } else {
                if (backgroundException != null) {
                    // Throw in the worker thread since the caller thread cannot get notifications.
                    throw new RealmException("Async transaction failed", backgroundException);
                }
            }
        }
    });
    return new RealmAsyncTaskImpl(pendingTransaction, asyncTaskExecutor);
}
Also used : RealmAsyncTaskImpl(io.realm.internal.async.RealmAsyncTaskImpl) RealmException(io.realm.exceptions.RealmException) RealmNotifier(io.realm.internal.RealmNotifier) OsSharedRealm(io.realm.internal.OsSharedRealm)

Aggregations

RealmNotifier (io.realm.internal.RealmNotifier)3 RealmException (io.realm.exceptions.RealmException)2 RealmAsyncTaskImpl (io.realm.internal.async.RealmAsyncTaskImpl)2 OsSharedRealm (io.realm.internal.OsSharedRealm)1 AndroidCapabilities (io.realm.internal.android.AndroidCapabilities)1 AndroidRealmNotifier (io.realm.internal.android.AndroidRealmNotifier)1 AppException (io.realm.mongodb.AppException)1