mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Clean up pre-rendered surfaces properly during teardowns (#39000)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/39000 Whenever React Native tears down (including on logout), we need to drop unconsumed Pre-rendering surfaces. D45012714 initially implemented this change, but this diff wasn't complete: it would only drop unconsumed pre-rendered surfaces when ***the Facebook infra* initiated** React Native to tear down. But, React Native could initiate tear down **by iteself** (e.g: via an uncaught exception on the Native Modules thread). ## Changes In this diff, make the React Manager support an onBeforeDestroy listener. Then, integrate these listeners into the teardown/reload algorithms. That way, no matter how React Native tears down, we **alwasy** drop unconsumed pre-rendered surfaces. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D48323647 fbshipit-source-id: 28f99500eea457b0e3c420fed28c434f8794ac23
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f437224042
commit
80b665966f
+57
-5
@@ -16,6 +16,7 @@ import static java.lang.Boolean.TRUE;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
@@ -71,6 +72,8 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
|
||||
/**
|
||||
* A ReactHost is an object that manages a single {@link ReactInstance}. A ReactHost can be
|
||||
@@ -128,6 +131,9 @@ public class ReactHostImpl implements ReactHost {
|
||||
private MemoryPressureListener mMemoryPressureListener;
|
||||
private @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler;
|
||||
|
||||
private final Set<Function0<Unit>> mBeforeDestroyListeners =
|
||||
Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
public ReactHostImpl(
|
||||
Context context,
|
||||
ReactHostDelegate delegate,
|
||||
@@ -677,6 +683,20 @@ public class ReactHostImpl implements ReactHost {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBeforeDestroyListener(@NonNull Function0<Unit> onBeforeDestroy) {
|
||||
synchronized (mBeforeDestroyListeners) {
|
||||
mBeforeDestroyListeners.add(onBeforeDestroy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBeforeDestroyListener(@NonNull Function0<Unit> onBeforeDestroy) {
|
||||
synchronized (mBeforeDestroyListeners) {
|
||||
mBeforeDestroyListeners.remove(onBeforeDestroy);
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ interface VeniceThenable<T> {
|
||||
void then(T t);
|
||||
}
|
||||
@@ -1294,9 +1314,25 @@ public class ReactHostImpl implements ReactHost {
|
||||
return task;
|
||||
},
|
||||
mBGExecutor)
|
||||
.continueWithTask(
|
||||
(task) -> {
|
||||
reactInstanceTaskUnwrapper.unwrap(
|
||||
task, "3: Executing Before Destroy Listeners");
|
||||
|
||||
Set<Function0<Unit>> beforeDestroyListeners;
|
||||
synchronized (mBeforeDestroyListeners) {
|
||||
beforeDestroyListeners = new HashSet<>(mBeforeDestroyListeners);
|
||||
}
|
||||
|
||||
for (Function0<Unit> destroyListener : beforeDestroyListeners) {
|
||||
destroyListener.invoke();
|
||||
}
|
||||
return task;
|
||||
},
|
||||
mUIExecutor)
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "3: Destroying ReactContext");
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "4: Destroying ReactContext");
|
||||
|
||||
log(method, "Removing memory pressure listener");
|
||||
mMemoryPressureRouter.removeMemoryPressureListener(mMemoryPressureListener);
|
||||
@@ -1320,7 +1356,7 @@ public class ReactHostImpl implements ReactHost {
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
final ReactInstance reactInstance =
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "4: Destroying ReactInstance");
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "5: Destroying ReactInstance");
|
||||
|
||||
if (reactInstance == null) {
|
||||
raiseSoftException(
|
||||
@@ -1346,7 +1382,7 @@ public class ReactHostImpl implements ReactHost {
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
final ReactInstance reactInstance =
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "5: Restarting surfaces");
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "7: Restarting surfaces");
|
||||
|
||||
if (reactInstance == null) {
|
||||
raiseSoftException(method, "Skipping surface restart: ReactInstance null");
|
||||
@@ -1463,7 +1499,23 @@ public class ReactHostImpl implements ReactHost {
|
||||
mBGExecutor)
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "3: Destroying ReactContext");
|
||||
reactInstanceTaskUnwrapper.unwrap(
|
||||
task, "3: Executing Before Destroy Listeners");
|
||||
|
||||
Set<Function0<Unit>> beforeDestroyListeners;
|
||||
synchronized (mBeforeDestroyListeners) {
|
||||
beforeDestroyListeners = new HashSet<>(mBeforeDestroyListeners);
|
||||
}
|
||||
|
||||
for (Function0<Unit> destroyListener : beforeDestroyListeners) {
|
||||
destroyListener.invoke();
|
||||
}
|
||||
return task;
|
||||
},
|
||||
mUIExecutor)
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "4: Destroying ReactContext");
|
||||
|
||||
final ReactContext reactContext = mBridgelessReactContextRef.getNullable();
|
||||
|
||||
@@ -1492,7 +1544,7 @@ public class ReactHostImpl implements ReactHost {
|
||||
.continueWithTask(
|
||||
task -> {
|
||||
final ReactInstance reactInstance =
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "3: Destroying ReactInstance");
|
||||
reactInstanceTaskUnwrapper.unwrap(task, "5: Destroying ReactInstance");
|
||||
|
||||
if (reactInstance == null) {
|
||||
raiseSoftException(
|
||||
|
||||
+4
@@ -101,4 +101,8 @@ interface ReactHost {
|
||||
* @return A task that completes when React Native gets destroyed.
|
||||
*/
|
||||
fun destroy(reason: String, ex: Exception?): TaskInterface<Void>
|
||||
|
||||
fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit)
|
||||
|
||||
fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user