Search code examples
androidrealm

Realm: Why on Devices/Emulators method RealmChangeListener.onChange() NOT call every times?


Realm 3.5.0

Android application.

My snippet:

public class MainApp extends MultiDexApplication implements RealmChangeListener<RealmResults<PermissionOfferResponse>> {

    private void loginAndConfig() {
        String authUrl = "http://" + BuildConfig.OBJECT_SERVER_IP + ":" + BuildConfig.OBJECT_SERVER_PORT + "/auth";

        SyncUser.Callback callback = new SyncUser.Callback() {
            @Override
            public void onSuccess(SyncUser user) {
                  syncUser = user;
                  createPermissionOfferAndSyncWithROS();
            }

            @Override
            public void onError(ObjectServerError error) {
                String errorMsg;
                switch (error.getErrorCode()) {
                    case UNKNOWN_ACCOUNT:
                        errorMsg = "Account does not exists.";
                        break;
                    case INVALID_CREDENTIALS:
                        errorMsg = "User name and password does not match";
                        break;
                    default:
                        errorMsg = error.toString();
                }
                Log.w(TAG, "loginAndConfig: onError: result errorMsg = " + errorMsg);
            }
        };

        SyncCredentials syncCredentials = SyncCredentials.usernamePassword(
                BuildConfig.USER_NAME, BuildConfig.PASSWORD, false);
        SyncUser.loginAsync(syncCredentials, authUrl, callback);
    }

    private void createPermissionOfferAndSyncWithROS() {
        Realm managementRealm = syncUser.getManagementRealm();
        String offerToken = BuildConfig.REALM_OFFER_TOKEN;
        final PermissionOfferResponse newPermissionOfferResponse = new PermissionOfferResponse(offerToken);
        managementRealm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.insert(newPermissionOfferResponse);
            }
        });

        RealmResults<PermissionOfferResponse> realmResultPermissionOfferResponse = managementRealm.where(PermissionOfferResponse.class)
                .equalTo("id", newPermissionOfferResponse.getId())
                .equalTo("statusCode", 0) // status > 0 is error
                .findAll();
        realmResultPermissionOfferResponse.addChangeListener(this);
    }

    @Override
    public void onChange(RealmResults<PermissionOfferResponse> permissionOfferResponse) {
        PermissionOfferResponse permissionOfferResponse = permissionOfferResponse.first();
        realmURL = permissionOfferResponse.getRealmUrl();
    }
}

My steps:

  1. Start Android application
  2. Check is method RealmChangeListener.onChange() was call
  3. Uninstall Android app

I repeat this 3 steps 10 TIMES.

Results on different Android configurations:

******************************************************
Emulator: Android 4.0.3, RAM 512 MB, VM Heap 48 MB
method RealmChangeListener.onChange() call 10 times.

******************************************************
Device: Android 4.3, RAM 700 MB
method RealmChangeListener.onChange() call ONLY 7 times.

******************************************************
Emulator: Android 6.0, RAM 512 MB, VM Heap 48 MB
method RealmChangeListener.onChange() call ONLY 7 times.

******************************************************
Emulator: Android 6.0, RAM 1 GB, VM Heap 48 MB
method RealmChangeListener.onChange() call ONLY 5 times.

******************************************************
Device: Android 6.0, RAM 2 GB
method RealmChangeListener.onChange() call 10 times.

Questions:

  1. Why on some Devices/Emulators method RealmChangeListener.onChange() NOT call 10 times?
  2. How I can fix this?

Thanks.


Solution

  • The following could work:

        private Set<RealmChangeListener<RealmResults<PermissionOfferResponse>> changeListeners = new HashSet<>();
    
        private void createPermissionOfferAndSyncWithROS() {
            Realm managementRealm = syncUser.getManagementRealm();
            String offerToken = BuildConfig.REALM_OFFER_TOKEN;
            final PermissionOfferResponse newPermissionOfferResponse = new PermissionOfferResponse(offerToken);
            managementRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    realm.insert(newPermissionOfferResponse);
                }
            });
    
            RealmResults<PermissionOfferResponse> realmResultPermissionOfferResponse = managementRealm.where(PermissionOfferResponse.class)
                    .equalTo("id", newPermissionOfferResponse.getId())
                    .equalTo("statusCode", 0) // status > 0 is error
                    .findAll();
    
            class _RealmChangeListener implements RealmChangeListener<RealmResults<PermissionOfferResponse>> {
                private RealmResults<PermissionOfferResponse> results;
    
                public _RealmChangeListener(RealmResults<PermissionOfferResponse> results) {
                    this.results = results;
                    changeListeners.add(this);
                    results.addChangeListener(this);
                }
    
                @Override
                public void onChange(RealmResults<PermissionOfferResponse> element) {
                    changeListeners.remove(this); 
                    MainApp.this.onChange(element);
                }
            }
            new _RealmChangeListener(realmResultPermissionOfferResponse);
        }
    
        public void onChange(RealmResults<PermissionOfferResponse> permissionOfferResponse) {
            PermissionOfferResponse permissionOfferResponse = permissionOfferResponse.first();
            realmURL = permissionOfferResponse.getRealmUrl();
        }
    }