Back out "[react-native][PR][Microsoft] This change fixes currently broken ReactContext listeners mechanism."

Summary: Original commit changeset: d506e5035a7f

Reviewed By: JoshuaGross

Differential Revision: D14689559

fbshipit-source-id: 9a8c8be0d2b7b9dd9be1ec038d7c3b356a5e3adf
This commit is contained in:
Christoph Nakazawa
2019-03-29 14:48:58 -07:00
committed by Facebook Github Bot
parent d2981af68f
commit 8b895ca710
2 changed files with 38 additions and 140 deletions

View File

@@ -18,6 +18,7 @@ import com.facebook.react.bridge.queue.MessageQueueThread;
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
import com.facebook.react.common.LifecycleState;
import java.lang.ref.WeakReference;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.annotation.Nullable;
/**
@@ -31,35 +32,10 @@ public class ReactContext extends ContextWrapper {
"ReactContext#getJSModule should only happen once initialize() has been called on your " +
"native module.";
private final SynchronizedWeakHashSet<LifecycleEventListener> mLifecycleEventListeners =
new SynchronizedWeakHashSet<>();
private final SynchronizedWeakHashSet<ActivityEventListener> mActivityEventListeners =
new SynchronizedWeakHashSet<>();
private final GuardedIteration<LifecycleEventListener> mResumeIteration =
new GuardedIteration<LifecycleEventListener>() {
@Override
public void onIterate(LifecycleEventListener listener) {
listener.onHostResume();
}
};
private final GuardedIteration<LifecycleEventListener> mPauseIteration =
new GuardedIteration<LifecycleEventListener>() {
@Override
public void onIterate(LifecycleEventListener listener) {
listener.onHostPause();
}
};
private final GuardedIteration<LifecycleEventListener> mDestroyIteration =
new GuardedIteration<LifecycleEventListener>() {
@Override
public void onIterate(LifecycleEventListener listener) {
listener.onHostDestroy();
}
};
private final CopyOnWriteArraySet<LifecycleEventListener> mLifecycleEventListeners =
new CopyOnWriteArraySet<>();
private final CopyOnWriteArraySet<ActivityEventListener> mActivityEventListeners =
new CopyOnWriteArraySet<>();
private LifecycleState mLifecycleState = LifecycleState.BEFORE_CREATE;
@@ -212,19 +188,26 @@ public class ReactContext extends ContextWrapper {
mLifecycleState = LifecycleState.RESUMED;
mCurrentActivity = new WeakReference(activity);
ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_RESUME_START);
mLifecycleEventListeners.iterate(mResumeIteration);
for (LifecycleEventListener listener : mLifecycleEventListeners) {
try {
listener.onHostResume();
} catch (RuntimeException e) {
handleException(e);
}
}
ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_RESUME_END);
}
public void onNewIntent(@Nullable Activity activity, final Intent intent) {
public void onNewIntent(@Nullable Activity activity, Intent intent) {
UiThreadUtil.assertOnUiThread();
mCurrentActivity = new WeakReference(activity);
mActivityEventListeners.iterate(new GuardedIteration<ActivityEventListener>() {
@Override
public void onIterate(ActivityEventListener listener) {
for (ActivityEventListener listener : mActivityEventListeners) {
try {
listener.onNewIntent(intent);
} catch (RuntimeException e) {
handleException(e);
}
});
}
}
/**
@@ -233,7 +216,13 @@ public class ReactContext extends ContextWrapper {
public void onHostPause() {
mLifecycleState = LifecycleState.BEFORE_RESUME;
ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_PAUSE_START);
mLifecycleEventListeners.iterate(mPauseIteration);
for (LifecycleEventListener listener : mLifecycleEventListeners) {
try {
listener.onHostPause();
} catch (RuntimeException e) {
handleException(e);
}
}
ReactMarker.logMarker(ReactMarkerConstants.ON_HOST_PAUSE_END);
}
@@ -243,7 +232,13 @@ public class ReactContext extends ContextWrapper {
public void onHostDestroy() {
UiThreadUtil.assertOnUiThread();
mLifecycleState = LifecycleState.BEFORE_CREATE;
mLifecycleEventListeners.iterate(mDestroyIteration);
for (LifecycleEventListener listener : mLifecycleEventListeners) {
try {
listener.onHostDestroy();
} catch (RuntimeException e) {
handleException(e);
}
}
mCurrentActivity = null;
}
@@ -261,13 +256,14 @@ public class ReactContext extends ContextWrapper {
/**
* Should be called by the hosting Fragment in {@link Fragment#onActivityResult}
*/
public void onActivityResult(final Activity activity, final int requestCode, final int resultCode, final Intent data) {
mActivityEventListeners.iterate(new GuardedIteration<ActivityEventListener>() {
@Override
public void onIterate(ActivityEventListener listener) {
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
for (ActivityEventListener listener : mActivityEventListeners) {
try {
listener.onActivityResult(activity, requestCode, resultCode, data);
} catch (RuntimeException e) {
handleException(e);
}
});
}
}
public void assertOnUiQueueThread() {
@@ -363,16 +359,4 @@ public class ReactContext extends ContextWrapper {
return mCatalystInstance.getJavaScriptContextHolder();
}
private abstract class GuardedIteration<T> implements SynchronizedWeakHashSet.Iteration<T> {
@Override
public void iterate(T listener) {
try {
onIterate(listener);
} catch (RuntimeException e) {
handleException(e);
}
}
public abstract void onIterate(T listener);
}
}

View File

@@ -1,86 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package com.facebook.react.bridge;
import android.util.Pair;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.WeakHashMap;
/**
* Thread-safe Set based on the WeakHashMap.
*
* Doesn't implement the `iterator` method because it's tricky to support modifications
* to the collection while somebody is using an `Iterator` to iterate over it.
*
* Instead, it provides an `iterate` method for traversing the collection. Any add/remove operations
* that occur during iteration are postponed until the iteration has completed.
*/
public class SynchronizedWeakHashSet<T> {
private WeakHashMap<T, Void> mMap = new WeakHashMap<>();
private Queue<Pair<T, Command>> mPendingOperations = new ArrayDeque<>();
private boolean mIterating;
public boolean contains(T item) {
synchronized (mMap) {
return mMap.containsKey(item);
}
}
public void add(T item) {
synchronized (mMap) {
if (mIterating) {
mPendingOperations.add(new Pair<>(item, Command.ADD));
} else {
mMap.put(item, null);
}
}
}
public void remove(T item) {
synchronized (mMap) {
if (mIterating) {
mPendingOperations.add(new Pair<>(item, Command.REMOVE));
} else {
mMap.remove(item);
}
}
}
public void iterate(Iteration<T> iterated) {
synchronized (mMap) {
// Protection from modification during iteration on the same thread
mIterating = true;
for (T listener: mMap.keySet()) {
iterated.iterate(listener);
}
mIterating = false;
while (!mPendingOperations.isEmpty()) {
Pair<T, Command> pair = mPendingOperations.poll();
switch (pair.second) {
case ADD:
mMap.put(pair.first, null);
break;
case REMOVE:
mMap.remove(pair.first);
break;
default:
throw new AssertionException("Unsupported command" + pair.second);
}
}
}
}
public interface Iteration<T> {
void iterate(T item);
}
private enum Command {
ADD,
REMOVE
}
}