Skip to content

Commit

Permalink
Refactor notify listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
nhachicha committed Feb 17, 2016
1 parent 9394cd7 commit 795cd6e
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@

package io.realm;

import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -57,18 +54,12 @@

@RunWith(AndroidJUnit4.class)
public class RealmAsyncQueryTests {
private Context context;

@Rule
public final RunInLooperThread looperThread = new RunInLooperThread();
@Rule
public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();

@Before
public void setUp() throws Exception {
context = InstrumentationRegistry.getInstrumentation().getContext();
}

// ****************************
// **** Async transaction ***
// ****************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@ public class RxJavaTests {
@Rule
public final TestRealmConfigurationFactory configFactory = new TestRealmConfigurationFactory();

private RealmConfiguration realmConfig;
private Realm realm;

@Before
public void setUp() throws Exception {
realmConfig = configFactory.createConfiguration();
RealmConfiguration realmConfig = configFactory.createConfiguration();
realm = Realm.getInstance(realmConfig);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,10 +855,15 @@ public void callback_with_relevant_commit_realmresults_async() {
@Override
public void onChange() {
// Step 4: Respond to relevant change
typebasedCommitInvocations.incrementAndGet();
assertEquals("Size wong", 1, dogs.size());
assertEquals("Akamaru", dogs.get(0).getName());
assertEquals(17, dogs.get(0).getAge());
int commits = typebasedCommitInvocations.incrementAndGet();
switch (commits) {
case 2:
assertEquals(17, dogs.get(0).getAge());
case 1:
assertEquals(1, dogs.size());
assertEquals("Akamaru", dogs.get(0).getName());

}
}
});

Expand All @@ -885,7 +890,7 @@ public void onChange() {
realm.handler.post(new Runnable() {
@Override
public void run() {
assertEquals("Typebased wrong", 1, typebasedCommitInvocations.get());
assertEquals(2, typebasedCommitInvocations.get());
looperThread.testComplete();
}
});
Expand Down
6 changes: 3 additions & 3 deletions realm/realm-library/src/main/java/io/realm/BaseRealm.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public void removeAllChangeListeners() {
handlerController.removeAllChangeListeners();
}

// WARNING: If this method is used after calling a any async method, the old handler will still be used.
// WARNING: If this method is used after calling any async method, the old handler will still be used.
// package private, for test purpose only
void setHandler(Handler handler) {
// remove the old one
handlers.remove(this.handler);
Expand Down Expand Up @@ -270,8 +271,7 @@ public void refresh() {
}
sharedGroupManager.advanceRead();
if (handlerController != null) {
handlerController.notifyGlobalListeners();
handlerController.notifyTypeBasedListeners();
handlerController.notifyAllListeners();
// if we have empty async RealmObject then rerun
if (handlerController.threadContainsAsyncEmptyRealmObject()) {
handlerController.updateAsyncEmptyRealmObject();
Expand Down
70 changes: 30 additions & 40 deletions realm/realm-library/src/main/java/io/realm/HandlerController.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,10 @@ public boolean handleMessage(Message message) {
}
case COMPLETED_UPDATE_ASYNC_QUERIES: {
// this is called once the background thread completed the update of the async queries
notifyAllListeners();
QueryUpdateTask.Result result = (QueryUpdateTask.Result) message.obj;
completedAsyncQueriesUpdate(result);
break;
}

case REALM_ASYNC_BACKGROUND_EXCEPTION: {
// Don't fail silently in the background in case of Core exception
throw (Error) message.obj;
Expand Down Expand Up @@ -178,14 +176,14 @@ void removeAllChangeListeners() {
void notifyGlobalListeners() {
// notify strong reference listener
Iterator<RealmChangeListener> iteratorStrongListeners = changeListeners.iterator();
while (iteratorStrongListeners.hasNext()) {
while (iteratorStrongListeners.hasNext() && !realm.isClosed()) { // every callback could close the realm
RealmChangeListener listener = iteratorStrongListeners.next();
listener.onChange();
}
// notify weak reference listener (internals)
Iterator<WeakReference<RealmChangeListener>> iteratorWeakListeners = weakChangeListeners.iterator();
List<WeakReference<RealmChangeListener>> toRemoveList = null;
while (iteratorWeakListeners.hasNext()) {
while (iteratorWeakListeners.hasNext() && !realm.isClosed()) {
WeakReference<RealmChangeListener> weakRef = iteratorWeakListeners.next();
RealmChangeListener listener = weakRef.get();
if (listener == null) {
Expand All @@ -202,12 +200,6 @@ void notifyGlobalListeners() {
}
}

void notifyTypeBasedListeners() {
notifyAsyncRealmResultsCallbacks();
notifySyncRealmResultsCallbacks();
notifyRealmObjectCallbacks();
}

void updateAsyncEmptyRealmObject() {
Iterator<Map.Entry<WeakReference<RealmObject>, RealmQuery<?>>> iterator = emptyAsyncRealmObject.entrySet().iterator();
while (iterator.hasNext()) {
Expand All @@ -228,6 +220,17 @@ void updateAsyncEmptyRealmObject() {
}
}

void notifyAllListeners() {
notifyGlobalListeners();
notifyTypeBasedListeners();
}

private void notifyTypeBasedListeners() {

This comment has been minimized.

Copy link
@beeender

beeender Feb 18, 2016

Contributor

Minor thing: We can move everything there to notifyAllListeners. It seems we never need to call those separately. I am also fine with what it is right now.

notifyAsyncRealmResultsCallbacks();
notifySyncRealmResultsCallbacks();
notifyRealmObjectCallbacks();
}

private void notifyAsyncRealmResultsCallbacks() {
notifyRealmResultsCallbacks(asyncRealmResults.keySet().iterator());
}
Expand All @@ -250,7 +253,8 @@ private void notifyRealmResultsCallbacks(Iterator<WeakReference<RealmResults<? e
}
}

for (RealmResults<? extends RealmObject> realmResults : resultsToBeNotified) {
for (Iterator<RealmResults<? extends RealmObject>> it = resultsToBeNotified.iterator(); it.hasNext() && !realm.isClosed(); ) {
RealmResults<? extends RealmObject> realmResults = it.next();
realmResults.notifyChangeListeners();
}
}
Expand All @@ -274,7 +278,8 @@ private void notifyRealmObjectCallbacks() {
}
}

for (RealmObject realmObject : objectsToBeNotified) {
for (Iterator<RealmObject> it = objectsToBeNotified.iterator(); it.hasNext() && !realm.isClosed(); ) {
RealmObject realmObject = it.next();
realmObject.notifyChangeListeners();
}
}
Expand Down Expand Up @@ -330,29 +335,16 @@ private void realmChanged() {
updateAsyncQueries();

} else {
RealmLog.d("REALM_CHANGED realm:"+ HandlerController.this + " no async queries, advance_read");
RealmLog.d("REALM_CHANGED realm:" + HandlerController.this + " no async queries, advance_read");
realm.sharedGroupManager.advanceRead();
notifyAllListeners();
}
}

private void notifyAllListeners() {
notifyGlobalListeners();
// notify RealmResults & RealmObject callbacks (type based notifications)
if (!realm.isClosed()) {
// Realm could be closed in the above listener.
notifySyncRealmResultsCallbacks();
}
if (!realm.isClosed()) {
notifyRealmObjectCallbacks();
}

// empty async RealmObject shouldn't block the realm to advance
// they're empty so no risk on running into a corrupt state
// where the pointer (Row) is using one version of a Realm, whereas the
// current Realm is advancing to a newer version (they're empty anyway)
if (!realm.isClosed() && threadContainsAsyncEmptyRealmObject()) {
updateAsyncEmptyRealmObject();
// empty async RealmObject shouldn't block the realm to advance
// they're empty so no risk on running into a corrupt state
// where the pointer (Row) is using one version of a Realm, whereas the
// current Realm is advancing to a newer version (they're empty anyway)
if (!realm.isClosed() && threadContainsAsyncEmptyRealmObject()) {
updateAsyncEmptyRealmObject();
}
}
}

Expand Down Expand Up @@ -474,13 +466,11 @@ private void completedAsyncQueriesUpdate(QueryUpdateTask.Result result) {
query.notifyChangeListeners();
}

// notify listeners only when we advanced
if (compare != 0) {
notifyGlobalListeners();
// notify RealmResults & RealmObject callbacks (type based notifications)
notifySyncRealmResultsCallbacks();
notifyRealmObjectCallbacks();
}
// We need to notify the rest of listeners, since the original REALM_CHANGE
// was delayed/swallowed in order to be able to update async queries
notifyGlobalListeners();
notifySyncRealmResultsCallbacks();
notifyRealmObjectCallbacks();

updateAsyncQueriesTask = null;
}
Expand Down

0 comments on commit 795cd6e

Please sign in to comment.