mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Format Java code in xplat/js/react-native-github
Summary: This diff formats the Java class files inside xplat/js/react-native-github. Since google-java-format was enabled in D16071401 we want to codemode the existing code so that users don't have to deal with formatter lint noise at diff-time. ```arc f --paths-cmd 'hg files -I "**/*.java"'``` drop-conflicts Reviewed By: cpojer Differential Revision: D16071725 fbshipit-source-id: fc6e3852e45742c109f0c5ac4065d64201c74204
This commit is contained in:
committed by
Facebook Github Bot
parent
61e95e5cbf
commit
6c0f73b322
@@ -11,6 +11,8 @@ import com.facebook.debug.debugoverlay.model.DebugOverlayTag;
|
||||
public interface Printer {
|
||||
|
||||
void logMessage(final DebugOverlayTag tag, final String message, Object... args);
|
||||
|
||||
void logMessage(final DebugOverlayTag tag, final String message);
|
||||
|
||||
boolean shouldDisplayLogMessage(final DebugOverlayTag tag);
|
||||
}
|
||||
|
||||
@@ -28,15 +28,9 @@ public class ReactDebugOverlayTags {
|
||||
"UI Manager View Operations (requires restart\nwarning: this is spammy)",
|
||||
Color.CYAN);
|
||||
public static final DebugOverlayTag FABRIC_UI_MANAGER =
|
||||
new DebugOverlayTag(
|
||||
"FabricUIManager",
|
||||
"Fabric UI Manager View Operations",
|
||||
Color.CYAN);
|
||||
new DebugOverlayTag("FabricUIManager", "Fabric UI Manager View Operations", Color.CYAN);
|
||||
public static final DebugOverlayTag FABRIC_RECONCILER =
|
||||
new DebugOverlayTag(
|
||||
"FabricReconciler",
|
||||
"Reconciler for Fabric",
|
||||
Color.CYAN);
|
||||
new DebugOverlayTag("FabricReconciler", "Reconciler for Fabric", Color.CYAN);
|
||||
public static final DebugOverlayTag RELAY =
|
||||
new DebugOverlayTag("Relay", "including prefetching", Color.rgb(0xFF, 0x99, 0x00));
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ import com.facebook.soloader.SoLoader;
|
||||
/**
|
||||
* A Java Object that has native memory allocated corresponding to this instance.
|
||||
*
|
||||
* NB: THREAD SAFETY (this comment also exists at Countable.cpp)
|
||||
* <p>NB: THREAD SAFETY (this comment also exists at Countable.cpp)
|
||||
*
|
||||
* {@link #dispose} deletes the corresponding native object on whatever thread the method is called
|
||||
* on. In the common case when this is called by Countable#finalize(), this will be called on the
|
||||
* system finalizer thread. If you manually call dispose on the Java object, the native object
|
||||
* <p>{@link #dispose} deletes the corresponding native object on whatever thread the method is
|
||||
* called on. In the common case when this is called by Countable#finalize(), this will be called on
|
||||
* the system finalizer thread. If you manually call dispose on the Java object, the native object
|
||||
* will be deleted synchronously on that thread.
|
||||
*/
|
||||
@DoNotStrip
|
||||
@@ -26,8 +26,7 @@ public class Countable {
|
||||
}
|
||||
|
||||
// Private C++ instance
|
||||
@DoNotStrip
|
||||
private long mInstance = 0;
|
||||
@DoNotStrip private long mInstance = 0;
|
||||
|
||||
public native void dispose();
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ package com.facebook.jni;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* Utility class to determine CPU capabilities
|
||||
*/
|
||||
/** Utility class to determine CPU capabilities */
|
||||
@DoNotStrip
|
||||
public class CpuCapabilitiesJni {
|
||||
|
||||
@@ -26,5 +24,4 @@ public class CpuCapabilitiesJni {
|
||||
|
||||
@DoNotStrip
|
||||
public static native boolean nativeDeviceSupportsX86();
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
/**
|
||||
* A thread which invokes the "destruct" routine for objects after they have been garbage collected.
|
||||
*
|
||||
* An object which needs to be destructed should create a static subclass of {@link Destructor}.
|
||||
* Once the referent object is garbage collected, the DestructorThread will callback to the
|
||||
* {@link Destructor#destruct()} method.
|
||||
* <p>An object which needs to be destructed should create a static subclass of {@link Destructor}.
|
||||
* Once the referent object is garbage collected, the DestructorThread will callback to the {@link
|
||||
* Destructor#destruct()} method.
|
||||
*
|
||||
* The underlying thread in DestructorThread starts when the first Destructor is constructed
|
||||
* and then runs indefinitely.
|
||||
* <p>The underlying thread in DestructorThread starts when the first Destructor is constructed and
|
||||
* then runs indefinitely.
|
||||
*/
|
||||
public class DestructorThread {
|
||||
|
||||
@@ -48,6 +48,7 @@ public class DestructorThread {
|
||||
private static DestructorList sDestructorList;
|
||||
/** A thread safe stack where new Destructors are placed before being add to sDestructorList. */
|
||||
private static DestructorStack sDestructorStack;
|
||||
|
||||
private static ReferenceQueue sReferenceQueue;
|
||||
private static Thread sThread;
|
||||
|
||||
@@ -55,27 +56,28 @@ public class DestructorThread {
|
||||
sDestructorStack = new DestructorStack();
|
||||
sReferenceQueue = new ReferenceQueue();
|
||||
sDestructorList = new DestructorList();
|
||||
sThread = new Thread("HybridData DestructorThread") {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Destructor current = (Destructor) sReferenceQueue.remove();
|
||||
current.destruct();
|
||||
sThread =
|
||||
new Thread("HybridData DestructorThread") {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Destructor current = (Destructor) sReferenceQueue.remove();
|
||||
current.destruct();
|
||||
|
||||
// If current is in the sDestructorStack,
|
||||
// transfer all the Destructors in the stack to the list.
|
||||
if (current.previous == null) {
|
||||
sDestructorStack.transferAllToList();
|
||||
// If current is in the sDestructorStack,
|
||||
// transfer all the Destructors in the stack to the list.
|
||||
if (current.previous == null) {
|
||||
sDestructorStack.transferAllToList();
|
||||
}
|
||||
|
||||
DestructorList.drop(current);
|
||||
} catch (InterruptedException e) {
|
||||
// Continue. This thread should never be terminated.
|
||||
}
|
||||
}
|
||||
|
||||
DestructorList.drop(current);
|
||||
} catch (InterruptedException e) {
|
||||
// Continue. This thread should never be terminated.
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
sThread.start();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
@DoNotStrip
|
||||
public abstract class HybridClassBase extends HybridData {
|
||||
}
|
||||
public abstract class HybridClassBase extends HybridData {}
|
||||
|
||||
@@ -5,19 +5,16 @@
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* This object holds a native C++ member for hybrid Java/C++ objects.
|
||||
*
|
||||
* NB: THREAD SAFETY
|
||||
* <p>NB: THREAD SAFETY
|
||||
*
|
||||
* {@link #resetNative} deletes the corresponding native object synchronously on whatever thread
|
||||
* the method is called on. Otherwise, deletion will occur on the {@link DestructorThread}
|
||||
* thread.
|
||||
* <p>{@link #resetNative} deletes the corresponding native object synchronously on whatever thread
|
||||
* the method is called on. Otherwise, deletion will occur on the {@link DestructorThread} thread.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class HybridData {
|
||||
@@ -26,26 +23,24 @@ public class HybridData {
|
||||
SoLoader.loadLibrary("fb");
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
private Destructor mDestructor = new Destructor(this);
|
||||
@DoNotStrip private Destructor mDestructor = new Destructor(this);
|
||||
|
||||
/**
|
||||
* To explicitly delete the instance, call resetNative(). If the C++
|
||||
* instance is referenced after this is called, a NullPointerException will
|
||||
* be thrown. resetNative() may be called multiple times safely. Because
|
||||
* the {@link DestructorThread} also calls resetNative, the instance will not leak if this is
|
||||
* not called, but timing of deletion and the thread the C++ dtor is called
|
||||
* on will be at the whim of the Java GC. If you want to control the thread
|
||||
* and timing of the destructor, you should call resetNative() explicitly.
|
||||
* To explicitly delete the instance, call resetNative(). If the C++ instance is referenced after
|
||||
* this is called, a NullPointerException will be thrown. resetNative() may be called multiple
|
||||
* times safely. Because the {@link DestructorThread} also calls resetNative, the instance will
|
||||
* not leak if this is not called, but timing of deletion and the thread the C++ dtor is called on
|
||||
* will be at the whim of the Java GC. If you want to control the thread and timing of the
|
||||
* destructor, you should call resetNative() explicitly.
|
||||
*/
|
||||
public synchronized void resetNative() {
|
||||
mDestructor.destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* N.B. Thread safety.
|
||||
* If you call isValid from a different thread than {@link #resetNative()} then be sure to
|
||||
* do so while synchronizing on the hybrid. For example:
|
||||
* N.B. Thread safety. If you call isValid from a different thread than {@link #resetNative()}
|
||||
* then be sure to do so while synchronizing on the hybrid. For example:
|
||||
*
|
||||
* <pre><code>
|
||||
* synchronized(hybrid) {
|
||||
* if (hybrid.isValid) {
|
||||
@@ -61,8 +56,7 @@ public class HybridData {
|
||||
public static class Destructor extends DestructorThread.Destructor {
|
||||
|
||||
// Private C++ instance
|
||||
@DoNotStrip
|
||||
private long mNativePointer;
|
||||
@DoNotStrip private long mNativePointer;
|
||||
|
||||
Destructor(Object referent) {
|
||||
super(referent);
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.jni;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
import java.util.Iterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* To iterate over an Iterator from C++ requires two calls per entry: hasNext()
|
||||
* and next(). This helper reduces it to one call and one field get per entry.
|
||||
* It does not use a generic argument, since in C++, the types will be erased,
|
||||
* anyway. This is *not* a {@link java.util.Iterator}.
|
||||
* To iterate over an Iterator from C++ requires two calls per entry: hasNext() and next(). This
|
||||
* helper reduces it to one call and one field get per entry. It does not use a generic argument,
|
||||
* since in C++, the types will be erased, anyway. This is *not* a {@link java.util.Iterator}.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class IteratorHelper {
|
||||
private final Iterator mIterator;
|
||||
|
||||
// This is private, but accessed via JNI.
|
||||
@DoNotStrip
|
||||
private @Nullable Object mElement;
|
||||
@DoNotStrip private @Nullable Object mElement;
|
||||
|
||||
@DoNotStrip
|
||||
public IteratorHelper(Iterator iterator) {
|
||||
@@ -38,8 +33,8 @@ public class IteratorHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the helper to the next entry in the map, if any. Returns true iff
|
||||
* there is an entry to read.
|
||||
* Moves the helper to the next entry in the map, if any. Returns true iff there is an entry to
|
||||
* read.
|
||||
*/
|
||||
@DoNotStrip
|
||||
boolean hasNext() {
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.jni;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* To iterate over a Map from C++ requires four calls per entry: hasNext(),
|
||||
* next(), getKey(), getValue(). This helper reduces it to one call and two
|
||||
* field gets per entry. It does not use a generic argument, since in C++, the
|
||||
* types will be erased, anyway. This is *not* a {@link java.util.Iterator}.
|
||||
* To iterate over a Map from C++ requires four calls per entry: hasNext(), next(), getKey(),
|
||||
* getValue(). This helper reduces it to one call and two field gets per entry. It does not use a
|
||||
* generic argument, since in C++, the types will be erased, anyway. This is *not* a {@link
|
||||
* java.util.Iterator}.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class MapIteratorHelper {
|
||||
@@ -32,8 +29,8 @@ public class MapIteratorHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the helper to the next entry in the map, if any. Returns true iff
|
||||
* there is an entry to read.
|
||||
* Moves the helper to the next entry in the map, if any. Returns true iff there is an entry to
|
||||
* read.
|
||||
*/
|
||||
@DoNotStrip
|
||||
boolean hasNext() {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.jni;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/**
|
||||
* A Runnable that has a native run implementation.
|
||||
*/
|
||||
/** A Runnable that has a native run implementation. */
|
||||
@DoNotStrip
|
||||
public class NativeRunnable implements Runnable {
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.perftest;
|
||||
|
||||
/**
|
||||
* PerfTestConfig stub.
|
||||
*/
|
||||
/** PerfTestConfig stub. */
|
||||
public class PerfTestConfig {
|
||||
|
||||
public boolean isRunningInPerfTest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.proguard.annotations;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
/**
|
||||
* Add this annotation to a class, method, or field to instruct Proguard to not strip it out.
|
||||
*
|
||||
* This is useful for methods called via reflection that could appear as unused to Proguard.
|
||||
* <p>This is useful for methods called via reflection that could appear as unused to Proguard.
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
|
||||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||
@Retention(CLASS)
|
||||
public @interface DoNotStrip {
|
||||
}
|
||||
public @interface DoNotStrip {}
|
||||
|
||||
+9
-11
@@ -1,28 +1,26 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.proguard.annotations;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
/**
|
||||
* Add this annotation to a class, to keep all "void set*(***)" and get* methods.
|
||||
*
|
||||
* <p>This is useful for classes that are controlled by animator-like classes that control
|
||||
* various properties with reflection.
|
||||
* <p>This is useful for classes that are controlled by animator-like classes that control various
|
||||
* properties with reflection.
|
||||
*
|
||||
* <p><b>NOTE:</b> This is <em>not</em> needed for Views because their getters and setters
|
||||
* are automatically kept by the default Android SDK ProGuard config.
|
||||
* <p><b>NOTE:</b> This is <em>not</em> needed for Views because their getters and setters are
|
||||
* automatically kept by the default Android SDK ProGuard config.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(CLASS)
|
||||
public @interface KeepGettersAndSetters {
|
||||
}
|
||||
public @interface KeepGettersAndSetters {}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import com.facebook.react.TurboReactPackage;
|
||||
|
||||
/**
|
||||
* {@code CompositeReactPackage} allows to create a single package composed of views and modules
|
||||
@@ -50,14 +49,14 @@ public class CompositeReactPackage implements ViewManagerOnDemandReactPackage, R
|
||||
final Map<String, NativeModule> moduleMap = new HashMap<>();
|
||||
for (ReactPackage reactPackage : mChildReactPackages) {
|
||||
/**
|
||||
* For now, we eagerly initialize the NativeModules inside TurboReactPackages.
|
||||
* Ultimately, we should turn CompositeReactPackage into a TurboReactPackage
|
||||
* and remove this eager initialization.
|
||||
* For now, we eagerly initialize the NativeModules inside TurboReactPackages. Ultimately, we
|
||||
* should turn CompositeReactPackage into a TurboReactPackage and remove this eager
|
||||
* initialization.
|
||||
*
|
||||
* TODO: T45627020
|
||||
* <p>TODO: T45627020
|
||||
*/
|
||||
if (reactPackage instanceof TurboReactPackage) {
|
||||
TurboReactPackage turboReactPackage = (TurboReactPackage)reactPackage;
|
||||
TurboReactPackage turboReactPackage = (TurboReactPackage) reactPackage;
|
||||
ReactModuleInfoProvider moduleInfoProvider = turboReactPackage.getReactModuleInfoProvider();
|
||||
Map<String, ReactModuleInfo> moduleInfos = moduleInfoProvider.getReactModuleInfos();
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
package com.facebook.react;
|
||||
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.*;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.PROCESS_CORE_REACT_PACKAGE_END;
|
||||
@@ -18,11 +19,11 @@ import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.module.annotations.ReactModuleList;
|
||||
import com.facebook.react.module.model.ReactModuleInfo;
|
||||
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.modules.core.ExceptionsManagerModule;
|
||||
import com.facebook.react.modules.core.Timing;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.HeadlessJsTaskSupportModule;
|
||||
import com.facebook.react.modules.core.Timing;
|
||||
import com.facebook.react.modules.debug.DevSettingsModule;
|
||||
import com.facebook.react.modules.debug.SourceCodeModule;
|
||||
import com.facebook.react.modules.deviceinfo.DeviceInfoModule;
|
||||
@@ -31,14 +32,10 @@ import com.facebook.react.uimanager.UIImplementationProvider;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.facebook.systrace.Systrace;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.*;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is the basic module to support React Native. The debug modules are now in DebugCorePackage.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import com.facebook.react.bridge.ModuleSpec;
|
||||
@@ -24,15 +23,13 @@ import javax.inject.Provider;
|
||||
* view managers from).
|
||||
*/
|
||||
@ReactModuleList(
|
||||
nativeModules = {
|
||||
JSCHeapCapture.class,
|
||||
JSDevSupport.class,
|
||||
}
|
||||
)
|
||||
nativeModules = {
|
||||
JSCHeapCapture.class,
|
||||
JSDevSupport.class,
|
||||
})
|
||||
/* package */ class DebugCorePackage extends LazyReactPackage {
|
||||
|
||||
DebugCorePackage() {
|
||||
}
|
||||
DebugCorePackage() {}
|
||||
|
||||
@Override
|
||||
public List<ModuleSpec> getNativeModules(final ReactApplicationContext reactContext) {
|
||||
|
||||
@@ -5,13 +5,10 @@
|
||||
|
||||
package com.facebook.react;
|
||||
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
|
||||
/**
|
||||
* Provider for an already initialized and non-lazy NativeModule.
|
||||
*/
|
||||
/** Provider for an already initialized and non-lazy NativeModule. */
|
||||
public class EagerModuleProvider implements Provider<NativeModule> {
|
||||
|
||||
private final NativeModule mModule;
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -19,23 +13,25 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskContext;
|
||||
import com.facebook.react.jstasks.HeadlessJsTaskEventListener;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for running JS without a UI. Generally, you only need to override
|
||||
* {@link #getTaskConfig}, which is called for every {@link #onStartCommand}. The
|
||||
* result, if not {@code null}, is used to run a JS task.
|
||||
* Base class for running JS without a UI. Generally, you only need to override {@link
|
||||
* #getTaskConfig}, which is called for every {@link #onStartCommand}. The result, if not {@code
|
||||
* null}, is used to run a JS task.
|
||||
*
|
||||
* If you need more fine-grained control over how tasks are run, you can override
|
||||
* {@link #onStartCommand} and call {@link #startTask} depending on your custom logic.
|
||||
* <p>If you need more fine-grained control over how tasks are run, you can override {@link
|
||||
* #onStartCommand} and call {@link #startTask} depending on your custom logic.
|
||||
*
|
||||
* If you're starting a {@code HeadlessJsTaskService} from a {@code BroadcastReceiver} (e.g.
|
||||
* <p>If you're starting a {@code HeadlessJsTaskService} from a {@code BroadcastReceiver} (e.g.
|
||||
* handling push notifications), make sure to call {@link #acquireWakeLockNow} before returning from
|
||||
* {@link BroadcastReceiver#onReceive}, to make sure the device doesn't go to sleep before the
|
||||
* service is started.
|
||||
@@ -57,9 +53,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
|
||||
/**
|
||||
* Called from {@link #onStartCommand} to create a {@link HeadlessJsTaskConfig} for this intent.
|
||||
*
|
||||
* @param intent the {@link Intent} received in {@link #onStartCommand}.
|
||||
* @return a {@link HeadlessJsTaskConfig} to be used with {@link #startTask}, or
|
||||
* {@code null} to ignore this command.
|
||||
* @return a {@link HeadlessJsTaskConfig} to be used with {@link #startTask}, or {@code null} to
|
||||
* ignore this command.
|
||||
*/
|
||||
protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
|
||||
return null;
|
||||
@@ -72,10 +69,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
public static void acquireWakeLockNow(Context context) {
|
||||
if (sWakeLock == null || !sWakeLock.isHeld()) {
|
||||
PowerManager powerManager =
|
||||
Assertions.assertNotNull((PowerManager) context.getSystemService(POWER_SERVICE));
|
||||
sWakeLock = powerManager.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK,
|
||||
HeadlessJsTaskService.class.getCanonicalName());
|
||||
Assertions.assertNotNull((PowerManager) context.getSystemService(POWER_SERVICE));
|
||||
sWakeLock =
|
||||
powerManager.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, HeadlessJsTaskService.class.getCanonicalName());
|
||||
sWakeLock.setReferenceCounted(false);
|
||||
sWakeLock.acquire();
|
||||
}
|
||||
@@ -89,7 +86,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
/**
|
||||
* Start a task. This method handles starting a new React instance if required.
|
||||
*
|
||||
* Has to be called on the UI thread.
|
||||
* <p>Has to be called on the UI thread.
|
||||
*
|
||||
* @param taskConfig describes what task to start and the parameters to pass to it
|
||||
*/
|
||||
@@ -97,17 +94,17 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
acquireWakeLockNow(this);
|
||||
final ReactInstanceManager reactInstanceManager =
|
||||
getReactNativeHost().getReactInstanceManager();
|
||||
getReactNativeHost().getReactInstanceManager();
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext == null) {
|
||||
reactInstanceManager
|
||||
.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(ReactContext reactContext) {
|
||||
invokeStartTask(reactContext, taskConfig);
|
||||
reactInstanceManager.removeReactInstanceEventListener(this);
|
||||
}
|
||||
});
|
||||
reactInstanceManager.addReactInstanceEventListener(
|
||||
new ReactInstanceManager.ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(ReactContext reactContext) {
|
||||
invokeStartTask(reactContext, taskConfig);
|
||||
reactInstanceManager.removeReactInstanceEventListener(this);
|
||||
}
|
||||
});
|
||||
reactInstanceManager.createReactContextInBackground();
|
||||
} else {
|
||||
invokeStartTask(reactContext, taskConfig);
|
||||
@@ -115,18 +112,18 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
}
|
||||
|
||||
private void invokeStartTask(ReactContext reactContext, final HeadlessJsTaskConfig taskConfig) {
|
||||
final HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext);
|
||||
final HeadlessJsTaskContext headlessJsTaskContext =
|
||||
HeadlessJsTaskContext.getInstance(reactContext);
|
||||
headlessJsTaskContext.addTaskEventListener(this);
|
||||
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int taskId = headlessJsTaskContext.startTask(taskConfig);
|
||||
mActiveTasks.add(taskId);
|
||||
}
|
||||
}
|
||||
);
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int taskId = headlessJsTaskContext.startTask(taskConfig);
|
||||
mActiveTasks.add(taskId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +135,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext != null) {
|
||||
HeadlessJsTaskContext headlessJsTaskContext =
|
||||
HeadlessJsTaskContext.getInstance(reactContext);
|
||||
HeadlessJsTaskContext.getInstance(reactContext);
|
||||
headlessJsTaskContext.removeTaskEventListener(this);
|
||||
}
|
||||
}
|
||||
@@ -148,7 +145,7 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeadlessJsTaskStart(int taskId) { }
|
||||
public void onHeadlessJsTaskStart(int taskId) {}
|
||||
|
||||
@Override
|
||||
public void onHeadlessJsTaskFinish(int taskId) {
|
||||
@@ -160,10 +157,10 @@ public abstract class HeadlessJsTaskService extends Service implements HeadlessJ
|
||||
|
||||
/**
|
||||
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link #getApplication()}
|
||||
* is an instance of {@link ReactApplication} and calls
|
||||
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
|
||||
* does not implement {@code ReactApplication} or you simply have a different mechanism for
|
||||
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
* is an instance of {@link ReactApplication} and calls {@link
|
||||
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
|
||||
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
|
||||
* {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
*/
|
||||
protected ReactNativeHost getReactNativeHost() {
|
||||
return ((ReactApplication) getApplication()).getReactNativeHost();
|
||||
|
||||
@@ -76,7 +76,8 @@ public abstract class LazyReactPackage implements ReactPackage {
|
||||
* @param reactContext
|
||||
* @return
|
||||
*/
|
||||
public Iterable<ModuleHolder> getNativeModuleIterator(final ReactApplicationContext reactContext) {
|
||||
public Iterable<ModuleHolder> getNativeModuleIterator(
|
||||
final ReactApplicationContext reactContext) {
|
||||
final Map<String, ReactModuleInfo> reactModuleInfoMap =
|
||||
getReactModuleInfoProvider().getReactModuleInfos();
|
||||
final List<ModuleSpec> nativeModules = getNativeModules(reactContext);
|
||||
|
||||
@@ -13,12 +13,10 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Translates and routes memory pressure events to the current catalyst instance.
|
||||
*/
|
||||
/** Translates and routes memory pressure events to the current catalyst instance. */
|
||||
public class MemoryPressureRouter implements ComponentCallbacks2 {
|
||||
private final Set<MemoryPressureListener> mListeners =
|
||||
Collections.synchronizedSet(new LinkedHashSet<MemoryPressureListener>());
|
||||
Collections.synchronizedSet(new LinkedHashSet<MemoryPressureListener>());
|
||||
|
||||
MemoryPressureRouter(Context context) {
|
||||
context.getApplicationContext().registerComponentCallbacks(this);
|
||||
@@ -28,16 +26,12 @@ public class MemoryPressureRouter implements ComponentCallbacks2 {
|
||||
context.getApplicationContext().unregisterComponentCallbacks(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to be notified of memory pressure events.
|
||||
*/
|
||||
/** Add a listener to be notified of memory pressure events. */
|
||||
public void addMemoryPressureListener(MemoryPressureListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener previously added with {@link #addMemoryPressureListener}.
|
||||
*/
|
||||
/** Remove a listener previously added with {@link #addMemoryPressureListener}. */
|
||||
public void removeMemoryPressureListener(MemoryPressureListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
@@ -48,18 +42,16 @@ public class MemoryPressureRouter implements ComponentCallbacks2 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
}
|
||||
public void onConfigurationChanged(Configuration newConfig) {}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
}
|
||||
public void onLowMemory() {}
|
||||
|
||||
private void dispatchMemoryPressure(int level) {
|
||||
// copy listeners array to avoid ConcurrentModificationException if any of the listeners remove
|
||||
// themselves in handleMemoryPressure()
|
||||
MemoryPressureListener[] listeners =
|
||||
mListeners.toArray(new MemoryPressureListener[mListeners.size()]);
|
||||
mListeners.toArray(new MemoryPressureListener[mListeners.size()]);
|
||||
for (MemoryPressureListener listener : listeners) {
|
||||
listener.handleMemoryPressure(level);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,8 @@ public class NativeModuleRegistryBuilder {
|
||||
// already in the list, and then NOT add the new module, since that will be directly exposed
|
||||
|
||||
// Note that is someone uses {@link NativeModuleRegistry#registerModules}, we will NOT check
|
||||
// for TurboModules - assuming that people wanted to explicitly register native modules there
|
||||
// for TurboModules - assuming that people wanted to explicitly register native modules
|
||||
// there
|
||||
continue;
|
||||
}
|
||||
mModules.put(name, moduleHolder);
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base Activity for React Native applications.
|
||||
*/
|
||||
/** Base Activity for React Native applications. */
|
||||
public abstract class ReactActivity extends AppCompatActivity
|
||||
implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
|
||||
|
||||
@@ -31,17 +26,14 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript.
|
||||
* This is used to schedule rendering of the component.
|
||||
* e.g. "MoviesApp"
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component. e.g. "MoviesApp"
|
||||
*/
|
||||
protected @Nullable String getMainComponentName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called at construction time, override if you have a custom delegate implementation.
|
||||
*/
|
||||
/** Called at construction time, override if you have a custom delegate implementation. */
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new ReactActivityDelegate(this, getMainComponentName());
|
||||
}
|
||||
@@ -111,17 +103,13 @@ public abstract class ReactActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void requestPermissions(
|
||||
String[] permissions,
|
||||
int requestCode,
|
||||
PermissionListener listener) {
|
||||
String[] permissions, int requestCode, PermissionListener listener) {
|
||||
mDelegate.requestPermissions(permissions, requestCode, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode,
|
||||
String[] permissions,
|
||||
int[] grantResults) {
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
mDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,9 @@ import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.uimanager.RootView;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@@ -54,11 +51,11 @@ public class ReactActivityDelegate {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ReactNativeHost} used by this app. By default, assumes
|
||||
* {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
|
||||
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
|
||||
* does not implement {@code ReactApplication} or you simply have a different mechanism for
|
||||
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link
|
||||
* Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link
|
||||
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
|
||||
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
|
||||
* {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
*/
|
||||
protected ReactNativeHost getReactNativeHost() {
|
||||
return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
|
||||
@@ -74,7 +71,9 @@ public class ReactActivityDelegate {
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
String mainComponentName = getMainComponentName();
|
||||
mReactDelegate = new ReactDelegate(getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions());
|
||||
mReactDelegate =
|
||||
new ReactDelegate(
|
||||
getPlainActivity(), getReactNativeHost(), mainComponentName, getLaunchOptions());
|
||||
if (mMainComponentName != null) {
|
||||
loadApp(mainComponentName);
|
||||
}
|
||||
@@ -108,8 +107,8 @@ public class ReactActivityDelegate {
|
||||
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (getReactNativeHost().hasInstance()
|
||||
&& getReactNativeHost().getUseDeveloperSupport()
|
||||
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
||||
&& getReactNativeHost().getUseDeveloperSupport()
|
||||
&& keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
|
||||
event.startTracking();
|
||||
return true;
|
||||
}
|
||||
@@ -150,25 +149,24 @@ public class ReactActivityDelegate {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public void requestPermissions(
|
||||
String[] permissions,
|
||||
int requestCode,
|
||||
PermissionListener listener) {
|
||||
String[] permissions, int requestCode, PermissionListener listener) {
|
||||
mPermissionListener = listener;
|
||||
getPlainActivity().requestPermissions(permissions, requestCode);
|
||||
}
|
||||
|
||||
public void onRequestPermissionsResult(
|
||||
final int requestCode,
|
||||
final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
mPermissionsCallback = new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
if (mPermissionListener != null && mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
mPermissionListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
final int requestCode, final String[] permissions, final int[] grantResults) {
|
||||
mPermissionsCallback =
|
||||
new Callback() {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
if (mPermissionListener != null
|
||||
&& mPermissionListener.onRequestPermissionsResult(
|
||||
requestCode, permissions, grantResults)) {
|
||||
mPermissionListener = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
|
||||
+25
-36
@@ -1,47 +1,42 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Responsible for dispatching events specific for hardware inputs.
|
||||
*/
|
||||
/** Responsible for dispatching events specific for hardware inputs. */
|
||||
public class ReactAndroidHWInputDeviceHelper {
|
||||
|
||||
/**
|
||||
* Contains a mapping between handled KeyEvents and the corresponding navigation event
|
||||
* that should be fired when the KeyEvent is received.
|
||||
* Contains a mapping between handled KeyEvents and the corresponding navigation event that should
|
||||
* be fired when the KeyEvent is received.
|
||||
*/
|
||||
private static final Map<Integer, String> KEY_EVENTS_ACTIONS = MapBuilder.<Integer, String>builder()
|
||||
.put(KeyEvent.KEYCODE_DPAD_CENTER, "select")
|
||||
.put(KeyEvent.KEYCODE_ENTER, "select")
|
||||
.put(KeyEvent.KEYCODE_SPACE, "select")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, "playPause")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_REWIND, "rewind")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, "fastForward")
|
||||
.put(KeyEvent.KEYCODE_DPAD_UP, "up")
|
||||
.put(KeyEvent.KEYCODE_DPAD_RIGHT, "right")
|
||||
.put(KeyEvent.KEYCODE_DPAD_DOWN, "down")
|
||||
.put(KeyEvent.KEYCODE_DPAD_LEFT, "left")
|
||||
.build();
|
||||
private static final Map<Integer, String> KEY_EVENTS_ACTIONS =
|
||||
MapBuilder.<Integer, String>builder()
|
||||
.put(KeyEvent.KEYCODE_DPAD_CENTER, "select")
|
||||
.put(KeyEvent.KEYCODE_ENTER, "select")
|
||||
.put(KeyEvent.KEYCODE_SPACE, "select")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, "playPause")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_REWIND, "rewind")
|
||||
.put(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, "fastForward")
|
||||
.put(KeyEvent.KEYCODE_DPAD_UP, "up")
|
||||
.put(KeyEvent.KEYCODE_DPAD_RIGHT, "right")
|
||||
.put(KeyEvent.KEYCODE_DPAD_DOWN, "down")
|
||||
.put(KeyEvent.KEYCODE_DPAD_LEFT, "left")
|
||||
.build();
|
||||
|
||||
/**
|
||||
* We keep a reference to the last focused view id
|
||||
* so that we can send it as a target for key events
|
||||
* and be able to send a blur event when focus changes.
|
||||
* We keep a reference to the last focused view id so that we can send it as a target for key
|
||||
* events and be able to send a blur event when focus changes.
|
||||
*/
|
||||
private int mLastFocusedViewId = View.NO_ID;
|
||||
|
||||
@@ -51,21 +46,17 @@ public class ReactAndroidHWInputDeviceHelper {
|
||||
this.mReactRootView = mReactRootView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link ReactRootView}.
|
||||
* This is the main place the key events are handled.
|
||||
*/
|
||||
/** Called from {@link ReactRootView}. This is the main place the key events are handled. */
|
||||
public void handleKeyEvent(KeyEvent ev) {
|
||||
int eventKeyCode = ev.getKeyCode();
|
||||
int eventKeyAction = ev.getAction();
|
||||
if ((eventKeyAction == KeyEvent.ACTION_UP || eventKeyAction == KeyEvent.ACTION_DOWN) && KEY_EVENTS_ACTIONS.containsKey(eventKeyCode)) {
|
||||
if ((eventKeyAction == KeyEvent.ACTION_UP || eventKeyAction == KeyEvent.ACTION_DOWN)
|
||||
&& KEY_EVENTS_ACTIONS.containsKey(eventKeyCode)) {
|
||||
dispatchEvent(KEY_EVENTS_ACTIONS.get(eventKeyCode), mLastFocusedViewId, eventKeyAction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link ReactRootView} when focused view changes.
|
||||
*/
|
||||
/** Called from {@link ReactRootView} when focused view changes. */
|
||||
public void onFocusChanged(View newFocusedView) {
|
||||
if (mLastFocusedViewId == newFocusedView.getId()) {
|
||||
return;
|
||||
@@ -77,9 +68,7 @@ public class ReactAndroidHWInputDeviceHelper {
|
||||
dispatchEvent("focus", newFocusedView.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link ReactRootView} when the whole view hierarchy looses focus.
|
||||
*/
|
||||
/** Called from {@link ReactRootView} when the whole view hierarchy looses focus. */
|
||||
public void clearFocus() {
|
||||
if (mLastFocusedViewId != View.NO_ID) {
|
||||
dispatchEvent("blur", mLastFocusedViewId);
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
public interface ReactApplication {
|
||||
|
||||
/**
|
||||
* Get the default {@link ReactNativeHost} for this app.
|
||||
*/
|
||||
/** Get the default {@link ReactNativeHost} for this app. */
|
||||
ReactNativeHost getReactNativeHost();
|
||||
}
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.devsupport.DoubleTapReloadRecognizer;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@@ -27,19 +24,19 @@ public class ReactDelegate {
|
||||
private final Activity mActivity;
|
||||
private ReactRootView mReactRootView;
|
||||
|
||||
@Nullable
|
||||
private final String mMainComponentName;
|
||||
@Nullable private final String mMainComponentName;
|
||||
|
||||
@Nullable
|
||||
private Bundle mLaunchOptions;
|
||||
@Nullable private Bundle mLaunchOptions;
|
||||
|
||||
@Nullable
|
||||
private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
|
||||
@Nullable private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
|
||||
|
||||
private ReactNativeHost mReactNativeHost;
|
||||
|
||||
|
||||
public ReactDelegate(Activity activity, ReactNativeHost reactNativeHost, @Nullable String appKey, @Nullable Bundle launchOptions) {
|
||||
public ReactDelegate(
|
||||
Activity activity,
|
||||
ReactNativeHost reactNativeHost,
|
||||
@Nullable String appKey,
|
||||
@Nullable Bundle launchOptions) {
|
||||
mActivity = activity;
|
||||
mMainComponentName = appKey;
|
||||
mLaunchOptions = launchOptions;
|
||||
@@ -50,9 +47,12 @@ public class ReactDelegate {
|
||||
public void onHostResume() {
|
||||
if (getReactNativeHost().hasInstance()) {
|
||||
if (mActivity instanceof DefaultHardwareBackBtnHandler) {
|
||||
getReactNativeHost().getReactInstanceManager().onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
|
||||
getReactNativeHost()
|
||||
.getReactInstanceManager()
|
||||
.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity);
|
||||
} else {
|
||||
throw new ClassCastException("Host Activity does not implement DefaultHardwareBackBtnHandler");
|
||||
throw new ClassCastException(
|
||||
"Host Activity does not implement DefaultHardwareBackBtnHandler");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,9 +81,12 @@ public class ReactDelegate {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
|
||||
public void onActivityResult(
|
||||
int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) {
|
||||
if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) {
|
||||
getReactNativeHost().getReactInstanceManager().onActivityResult(mActivity, requestCode, resultCode, data);
|
||||
getReactNativeHost()
|
||||
.getReactInstanceManager()
|
||||
.onActivityResult(mActivity, requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,26 +100,23 @@ public class ReactDelegate {
|
||||
}
|
||||
mReactRootView = createRootView();
|
||||
mReactRootView.startReactApplication(
|
||||
getReactNativeHost().getReactInstanceManager(),
|
||||
appKey,
|
||||
mLaunchOptions);
|
||||
|
||||
getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);
|
||||
}
|
||||
|
||||
public ReactRootView getReactRootView() {
|
||||
return mReactRootView;
|
||||
}
|
||||
|
||||
|
||||
protected ReactRootView createRootView() {
|
||||
return new ReactRootView(mActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether
|
||||
* the application should show the developer menu or should reload the React Application.
|
||||
* Handles delegating the {@link Activity#onKeyUp(int, KeyEvent)} method to determine whether the
|
||||
* application should show the developer menu or should reload the React Application.
|
||||
*
|
||||
* @return true if we consume the event and either shoed the develop menu or reloaded the application.
|
||||
* @return true if we consume the event and either shoed the develop menu or reloaded the
|
||||
* application.
|
||||
*/
|
||||
public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) {
|
||||
if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) {
|
||||
@@ -124,7 +124,9 @@ public class ReactDelegate {
|
||||
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
|
||||
return true;
|
||||
}
|
||||
boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, mActivity.getCurrentFocus());
|
||||
boolean didDoubleTapR =
|
||||
Assertions.assertNotNull(mDoubleTapReloadRecognizer)
|
||||
.didDoubleTapR(keyCode, mActivity.getCurrentFocus());
|
||||
if (didDoubleTapR) {
|
||||
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
|
||||
return true;
|
||||
@@ -133,9 +135,7 @@ public class ReactDelegate {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ReactNativeHost} used by this app.
|
||||
*/
|
||||
/** Get the {@link ReactNativeHost} used by this app. */
|
||||
private ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
@@ -143,5 +143,4 @@ public class ReactDelegate {
|
||||
public ReactInstanceManager getReactInstanceManager() {
|
||||
return getReactNativeHost().getReactInstanceManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* <p>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;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
@@ -17,194 +15,188 @@ import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import com.facebook.react.modules.core.PermissionAwareActivity;
|
||||
import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
/**
|
||||
* Fragment for creating a React View. This allows the developer to "embed" a React Application
|
||||
* inside native components such as a Drawer, ViewPager, etc.
|
||||
*/
|
||||
* Fragment for creating a React View. This allows the developer to "embed" a React Application
|
||||
* inside native components such as a Drawer, ViewPager, etc.
|
||||
*/
|
||||
public class ReactFragment extends Fragment implements PermissionAwareActivity {
|
||||
|
||||
private static final String ARG_COMPONENT_NAME = "arg_component_name";
|
||||
private static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
|
||||
private static final String ARG_COMPONENT_NAME = "arg_component_name";
|
||||
private static final String ARG_LAUNCH_OPTIONS = "arg_launch_options";
|
||||
|
||||
private ReactDelegate mReactDelegate;
|
||||
private ReactDelegate mReactDelegate;
|
||||
|
||||
@Nullable
|
||||
private PermissionListener mPermissionListener;
|
||||
@Nullable private PermissionListener mPermissionListener;
|
||||
|
||||
|
||||
public ReactFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* @param componentName The name of the react native component
|
||||
* @return A new instance of fragment ReactFragment.
|
||||
*/
|
||||
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
|
||||
ReactFragment fragment = new ReactFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_COMPONENT_NAME, componentName);
|
||||
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String mainComponentName = null;
|
||||
Bundle launchOptions = null;
|
||||
if (getArguments() != null) {
|
||||
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
|
||||
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
|
||||
}
|
||||
if (mainComponentName == null) {
|
||||
throw new IllegalStateException("Cannot loadApp if component name is null");
|
||||
}
|
||||
mReactDelegate = new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ReactNativeHost} used by this app. By default, assumes
|
||||
* {@link Activity#getApplication()} is an instance of {@link ReactApplication} and calls
|
||||
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
|
||||
* does not implement {@code ReactApplication} or you simply have a different mechanism for
|
||||
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
*/
|
||||
protected ReactNativeHost getReactNativeHost() {
|
||||
return ((ReactApplication) getActivity().getApplication()).getReactNativeHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
mReactDelegate.loadApp();
|
||||
return mReactDelegate.getReactRootView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mReactDelegate.onHostResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mReactDelegate.onHostPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mReactDelegate.onHostDestroy();
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
mReactDelegate.onActivityResult(requestCode, resultCode, data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to forward hardware back presses to our React Native Host
|
||||
*
|
||||
* This must be called via a forward from your host Activity
|
||||
*
|
||||
*/
|
||||
public boolean onBackPressed() {
|
||||
return mReactDelegate.onBackPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to forward onKeyUp commands from our host Activity.
|
||||
* This allows ReactFragment to handle double tap reloads and dev menus
|
||||
*
|
||||
* This must be called via a forward from your host Activity
|
||||
*
|
||||
* @param keyCode keyCode
|
||||
* @param event event
|
||||
* @return true if we handled onKeyUp
|
||||
*/
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (mPermissionListener != null &&
|
||||
mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
mPermissionListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkPermission(String permission, int pid, int uid) {
|
||||
return getActivity().checkPermission(permission, pid, uid);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public int checkSelfPermission(String permission) {
|
||||
return getActivity().checkSelfPermission(permission);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
|
||||
mPermissionListener = listener;
|
||||
requestPermissions(permissions, requestCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class to help instantiate a ReactFragment
|
||||
*/
|
||||
public static class Builder {
|
||||
|
||||
String mComponentName;
|
||||
Bundle mLaunchOptions;
|
||||
|
||||
public Builder() {
|
||||
mComponentName = null;
|
||||
mLaunchOptions = null;
|
||||
public ReactFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Component name for our React Native instance.
|
||||
*
|
||||
* @param componentName The name of the component
|
||||
* @return Builder
|
||||
* @param componentName The name of the react native component
|
||||
* @return A new instance of fragment ReactFragment.
|
||||
*/
|
||||
public Builder setComponentName(String componentName) {
|
||||
mComponentName = componentName;
|
||||
return this;
|
||||
private static ReactFragment newInstance(String componentName, Bundle launchOptions) {
|
||||
ReactFragment fragment = new ReactFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_COMPONENT_NAME, componentName);
|
||||
args.putBundle(ARG_LAUNCH_OPTIONS, launchOptions);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String mainComponentName = null;
|
||||
Bundle launchOptions = null;
|
||||
if (getArguments() != null) {
|
||||
mainComponentName = getArguments().getString(ARG_COMPONENT_NAME);
|
||||
launchOptions = getArguments().getBundle(ARG_LAUNCH_OPTIONS);
|
||||
}
|
||||
if (mainComponentName == null) {
|
||||
throw new IllegalStateException("Cannot loadApp if component name is null");
|
||||
}
|
||||
mReactDelegate =
|
||||
new ReactDelegate(getActivity(), getReactNativeHost(), mainComponentName, launchOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Launch Options for our React Native instance.
|
||||
*
|
||||
* @param launchOptions launchOptions
|
||||
* @return Builder
|
||||
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link
|
||||
* Activity#getApplication()} is an instance of {@link ReactApplication} and calls {@link
|
||||
* ReactApplication#getReactNativeHost()}. Override this method if your application class does not
|
||||
* implement {@code ReactApplication} or you simply have a different mechanism for storing a
|
||||
* {@code ReactNativeHost}, e.g. as a static field somewhere.
|
||||
*/
|
||||
public Builder setLaunchOptions(Bundle launchOptions) {
|
||||
mLaunchOptions = launchOptions;
|
||||
return this;
|
||||
protected ReactNativeHost getReactNativeHost() {
|
||||
return ((ReactApplication) getActivity().getApplication()).getReactNativeHost();
|
||||
}
|
||||
|
||||
public ReactFragment build() {
|
||||
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
mReactDelegate.loadApp();
|
||||
return mReactDelegate.getReactRootView();
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mReactDelegate.onHostResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mReactDelegate.onHostPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mReactDelegate.onHostDestroy();
|
||||
}
|
||||
// endregion
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
mReactDelegate.onActivityResult(requestCode, resultCode, data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to forward hardware back presses to our React Native Host
|
||||
*
|
||||
* <p>This must be called via a forward from your host Activity
|
||||
*/
|
||||
public boolean onBackPressed() {
|
||||
return mReactDelegate.onBackPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to forward onKeyUp commands from our host Activity. This allows ReactFragment to handle
|
||||
* double tap reloads and dev menus
|
||||
*
|
||||
* <p>This must be called via a forward from your host Activity
|
||||
*
|
||||
* @param keyCode keyCode
|
||||
* @param event event
|
||||
* @return true if we handled onKeyUp
|
||||
*/
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
return mReactDelegate.shouldShowDevMenuOrReload(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(
|
||||
int requestCode, String[] permissions, int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (mPermissionListener != null
|
||||
&& mPermissionListener.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
|
||||
mPermissionListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkPermission(String permission, int pid, int uid) {
|
||||
return getActivity().checkPermission(permission, pid, uid);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public int checkSelfPermission(String permission) {
|
||||
return getActivity().checkSelfPermission(permission);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@Override
|
||||
public void requestPermissions(
|
||||
String[] permissions, int requestCode, PermissionListener listener) {
|
||||
mPermissionListener = listener;
|
||||
requestPermissions(permissions, requestCode);
|
||||
}
|
||||
|
||||
/** Builder class to help instantiate a ReactFragment */
|
||||
public static class Builder {
|
||||
|
||||
String mComponentName;
|
||||
Bundle mLaunchOptions;
|
||||
|
||||
public Builder() {
|
||||
mComponentName = null;
|
||||
mLaunchOptions = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Component name for our React Native instance.
|
||||
*
|
||||
* @param componentName The name of the component
|
||||
* @return Builder
|
||||
*/
|
||||
public Builder setComponentName(String componentName) {
|
||||
mComponentName = componentName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Launch Options for our React Native instance.
|
||||
*
|
||||
* @param launchOptions launchOptions
|
||||
* @return Builder
|
||||
*/
|
||||
public Builder setLaunchOptions(Bundle launchOptions) {
|
||||
mLaunchOptions = launchOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactFragment build() {
|
||||
return ReactFragment.newInstance(mComponentName, mLaunchOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* ReactFragmentActivity will be removed in 0.59 release.
|
||||
* Use {@link ReactActivity} instead.
|
||||
* @deprecated ReactFragmentActivity will be removed in 0.59 release. Use {@link ReactActivity}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class ReactFragmentActivity extends ReactActivity {
|
||||
}
|
||||
public abstract class ReactFragmentActivity extends ReactActivity {}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import static com.facebook.infer.annotation.ThreadConfined.UI;
|
||||
@@ -12,6 +11,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROO
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.ATTACH_MEASURED_ROOT_VIEWS_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.BUILD_NATIVE_MODULE_REGISTRY_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_CATALYST_INSTANCE_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_REACT_CONTEXT_START;
|
||||
@@ -25,7 +25,6 @@ import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREA
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.REACT_CONTEXT_THREAD_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.SETUP_REACT_CONTEXT_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CHANGE_THREAD_PRIORITY;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.VM_INIT;
|
||||
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
|
||||
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_APPS;
|
||||
@@ -38,9 +37,9 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.debug.holder.PrinterHolder;
|
||||
import com.facebook.debug.tags.ReactDebugOverlayTags;
|
||||
@@ -107,28 +106,26 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class is managing instances of {@link CatalystInstance}. It exposes a way to configure
|
||||
* catalyst instance using {@link ReactPackage} and keeps track of the lifecycle of that
|
||||
* instance. It also sets up connection between the instance and developers support functionality
|
||||
* of the framework.
|
||||
* catalyst instance using {@link ReactPackage} and keeps track of the lifecycle of that instance.
|
||||
* It also sets up connection between the instance and developers support functionality of the
|
||||
* framework.
|
||||
*
|
||||
* An instance of this manager is required to start JS application in {@link ReactRootView} (see
|
||||
* <p>An instance of this manager is required to start JS application in {@link ReactRootView} (see
|
||||
* {@link ReactRootView#startReactApplication} for more info).
|
||||
*
|
||||
* The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the
|
||||
* activity that owns the {@link ReactRootView} that is used to render react application using this
|
||||
* instance manager (see {@link ReactRootView#startReactApplication}). It's required to pass owning
|
||||
* <p>The lifecycle of the instance of {@link ReactInstanceManager} should be bound to the activity
|
||||
* that owns the {@link ReactRootView} that is used to render react application using this instance
|
||||
* manager (see {@link ReactRootView#startReactApplication}). It's required to pass owning
|
||||
* activity's lifecycle events to the instance manager (see {@link #onHostPause}, {@link
|
||||
* #onHostDestroy} and {@link #onHostResume}).
|
||||
*
|
||||
* To instantiate an instance of this class use {@link #builder}.
|
||||
* <p>To instantiate an instance of this class use {@link #builder}.
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ReactInstanceManager {
|
||||
|
||||
private static final String TAG = ReactInstanceManager.class.getSimpleName();
|
||||
/**
|
||||
* Listener interface for react instance events.
|
||||
*/
|
||||
/** Listener interface for react instance events. */
|
||||
public interface ReactInstanceEventListener {
|
||||
|
||||
/**
|
||||
@@ -138,8 +135,8 @@ public class ReactInstanceManager {
|
||||
void onReactContextInitialized(ReactContext context);
|
||||
}
|
||||
|
||||
private final Set<ReactRoot> mAttachedReactRoots = Collections.synchronizedSet(
|
||||
new HashSet<ReactRoot>());
|
||||
private final Set<ReactRoot> mAttachedReactRoots =
|
||||
Collections.synchronizedSet(new HashSet<ReactRoot>());
|
||||
|
||||
private volatile LifecycleState mLifecycleState;
|
||||
|
||||
@@ -176,8 +173,7 @@ public class ReactInstanceManager {
|
||||
private final JSBundleLoader mJsBundleLoader;
|
||||
|
||||
public ReactContextInitParams(
|
||||
JavaScriptExecutorFactory jsExecutorFactory,
|
||||
JSBundleLoader jsBundleLoader) {
|
||||
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
|
||||
mJsExecutorFactory = Assertions.assertNotNull(jsExecutorFactory);
|
||||
mJsBundleLoader = Assertions.assertNotNull(jsBundleLoader);
|
||||
}
|
||||
@@ -191,33 +187,31 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}.
|
||||
*/
|
||||
/** Creates a builder that is capable of creating an instance of {@link ReactInstanceManager}. */
|
||||
public static ReactInstanceManagerBuilder builder() {
|
||||
return new ReactInstanceManagerBuilder();
|
||||
}
|
||||
|
||||
/* package */ ReactInstanceManager(
|
||||
Context applicationContext,
|
||||
@Nullable Activity currentActivity,
|
||||
@Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
|
||||
JavaScriptExecutorFactory javaScriptExecutorFactory,
|
||||
@Nullable JSBundleLoader bundleLoader,
|
||||
@Nullable String jsMainModulePath,
|
||||
List<ReactPackage> packages,
|
||||
boolean useDeveloperSupport,
|
||||
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
|
||||
LifecycleState initialLifecycleState,
|
||||
@Nullable UIImplementationProvider mUIImplementationProvider,
|
||||
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
boolean lazyViewManagersEnabled,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
int minTimeLeftInFrameForNonBatchedOperationMs,
|
||||
@Nullable JSIModulePackage jsiModulePackage,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
|
||||
Context applicationContext,
|
||||
@Nullable Activity currentActivity,
|
||||
@Nullable DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler,
|
||||
JavaScriptExecutorFactory javaScriptExecutorFactory,
|
||||
@Nullable JSBundleLoader bundleLoader,
|
||||
@Nullable String jsMainModulePath,
|
||||
List<ReactPackage> packages,
|
||||
boolean useDeveloperSupport,
|
||||
@Nullable NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener,
|
||||
LifecycleState initialLifecycleState,
|
||||
@Nullable UIImplementationProvider mUIImplementationProvider,
|
||||
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler,
|
||||
@Nullable RedBoxHandler redBoxHandler,
|
||||
boolean lazyViewManagersEnabled,
|
||||
@Nullable DevBundleDownloadListener devBundleDownloadListener,
|
||||
int minNumShakes,
|
||||
int minTimeLeftInFrameForNonBatchedOperationMs,
|
||||
@Nullable JSIModulePackage jsiModulePackage,
|
||||
@Nullable Map<String, RequestHandler> customPackagerCommandHandlers) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.ctor()");
|
||||
initializeSoLoaderIfNecessary(applicationContext);
|
||||
|
||||
@@ -326,10 +320,10 @@ public class ReactInstanceManager {
|
||||
|
||||
/**
|
||||
* Trigger react context initialization asynchronously in a background async task. This enables
|
||||
* applications to pre-load the application JS, and execute global code before
|
||||
* {@link ReactRootView} is available and measured.
|
||||
* applications to pre-load the application JS, and execute global code before {@link
|
||||
* ReactRootView} is available and measured.
|
||||
*
|
||||
* Called from UI thread.
|
||||
* <p>Called from UI thread.
|
||||
*/
|
||||
@ThreadConfined(UI)
|
||||
public void createReactContextInBackground() {
|
||||
@@ -351,8 +345,8 @@ public class ReactInstanceManager {
|
||||
public void recreateReactContextInBackground() {
|
||||
Assertions.assertCondition(
|
||||
mHasStartedCreatingInitialContext,
|
||||
"recreateReactContextInBackground should only be called after the initial " +
|
||||
"createReactContextInBackground call.");
|
||||
"recreateReactContextInBackground should only be called after the initial "
|
||||
+ "createReactContextInBackground call.");
|
||||
recreateReactContextInBackgroundInner();
|
||||
}
|
||||
|
||||
@@ -367,8 +361,8 @@ public class ReactInstanceManager {
|
||||
final DeveloperSettings devSettings = mDevSupportManager.getDevSettings();
|
||||
|
||||
// If remote JS debugging is enabled, load from dev server.
|
||||
if (mDevSupportManager.hasUpToDateJSBundleInCache() &&
|
||||
!devSettings.isRemoteJSDebugEnabled()) {
|
||||
if (mDevSupportManager.hasUpToDateJSBundleInCache()
|
||||
&& !devSettings.isRemoteJSDebugEnabled()) {
|
||||
// If there is a up-to-date bundle downloaded from server,
|
||||
// with remote JS debugging disabled, always use that.
|
||||
onJSBundleLoadedFromServer(null);
|
||||
@@ -409,8 +403,8 @@ public class ReactInstanceManager {
|
||||
@ThreadConfined(UI)
|
||||
private void recreateReactContextInBackgroundFromBundleLoader() {
|
||||
Log.d(
|
||||
ReactConstants.TAG,
|
||||
"ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
|
||||
ReactConstants.TAG,
|
||||
"ReactInstanceManager.recreateReactContextInBackgroundFromBundleLoader()");
|
||||
PrinterHolder.getPrinter()
|
||||
.logMessage(ReactDebugOverlayTags.RN_CORE, "RNCore: load from BundleLoader");
|
||||
recreateReactContextInBackground(mJavaScriptExecutorFactory, mBundleLoader);
|
||||
@@ -418,7 +412,7 @@ public class ReactInstanceManager {
|
||||
|
||||
/**
|
||||
* @return whether createReactContextInBackground has been called. Will return false after
|
||||
* onDestroy until a new initial context has been created.
|
||||
* onDestroy until a new initial context has been created.
|
||||
*/
|
||||
public boolean hasStartedCreatingInitialContext() {
|
||||
return mHasStartedCreatingInitialContext;
|
||||
@@ -437,7 +431,7 @@ public class ReactInstanceManager {
|
||||
invokeDefaultOnBackPressed();
|
||||
} else {
|
||||
DeviceEventManagerModule deviceEventManagerModule =
|
||||
reactContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
reactContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
deviceEventManagerModule.emitHardwareBackPressed();
|
||||
}
|
||||
}
|
||||
@@ -449,9 +443,7 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will give JS the opportunity to receive intents via Linking.
|
||||
*/
|
||||
/** This method will give JS the opportunity to receive intents via Linking. */
|
||||
@ThreadConfined(UI)
|
||||
public void onNewIntent(Intent intent) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
@@ -464,7 +456,7 @@ public class ReactInstanceManager {
|
||||
|
||||
if (Intent.ACTION_VIEW.equals(action) && uri != null) {
|
||||
DeviceEventManagerModule deviceEventManagerModule =
|
||||
currentContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
currentContext.getNativeModule(DeviceEventManagerModule.class);
|
||||
deviceEventManagerModule.emitNewIntentReceived(uri);
|
||||
}
|
||||
currentContext.onNewIntent(mCurrentActivity, intent);
|
||||
@@ -501,8 +493,8 @@ public class ReactInstanceManager {
|
||||
/**
|
||||
* Call this from {@link Activity#onPause()}. This notifies any listening modules so they can do
|
||||
* any necessary cleanup. The passed Activity is the current Activity being paused. This will
|
||||
* always be the foreground activity that would be returned by
|
||||
* {@link ReactContext#getCurrentActivity()}.
|
||||
* always be the foreground activity that would be returned by {@link
|
||||
* ReactContext#getCurrentActivity()}.
|
||||
*
|
||||
* @param activity the activity being paused
|
||||
*/
|
||||
@@ -510,23 +502,26 @@ public class ReactInstanceManager {
|
||||
public void onHostPause(Activity activity) {
|
||||
Assertions.assertNotNull(mCurrentActivity);
|
||||
Assertions.assertCondition(
|
||||
activity == mCurrentActivity,
|
||||
"Pausing an activity that is not the current activity, this is incorrect! " +
|
||||
"Current activity: " + mCurrentActivity.getClass().getSimpleName() + " " +
|
||||
"Paused activity: " + activity.getClass().getSimpleName());
|
||||
activity == mCurrentActivity,
|
||||
"Pausing an activity that is not the current activity, this is incorrect! "
|
||||
+ "Current activity: "
|
||||
+ mCurrentActivity.getClass().getSimpleName()
|
||||
+ " "
|
||||
+ "Paused activity: "
|
||||
+ activity.getClass().getSimpleName());
|
||||
onHostPause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method when the activity resumes to enable invoking the back button directly from JS.
|
||||
*
|
||||
* This method retains an instance to provided mDefaultBackButtonImpl. Thus it's important to pass
|
||||
* from the activity instance that owns this particular instance of {@link
|
||||
* ReactInstanceManager}, so that once this instance receive {@link #onHostDestroy} event it
|
||||
* will clear the reference to that defaultBackButtonImpl.
|
||||
* <p>This method retains an instance to provided mDefaultBackButtonImpl. Thus it's important to
|
||||
* pass from the activity instance that owns this particular instance of {@link
|
||||
* ReactInstanceManager}, so that once this instance receive {@link #onHostDestroy} event it will
|
||||
* clear the reference to that defaultBackButtonImpl.
|
||||
*
|
||||
* @param defaultBackButtonImpl a {@link DefaultHardwareBackBtnHandler} from an Activity that owns
|
||||
* this instance of {@link ReactInstanceManager}.
|
||||
* this instance of {@link ReactInstanceManager}.
|
||||
*/
|
||||
@ThreadConfined(UI)
|
||||
public void onHostResume(Activity activity, DefaultHardwareBackBtnHandler defaultBackButtonImpl) {
|
||||
@@ -536,9 +531,7 @@ public class ReactInstanceManager {
|
||||
onHostResume(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method when the activity resumes.
|
||||
*/
|
||||
/** Use this method when the activity resumes. */
|
||||
@ThreadConfined(UI)
|
||||
public void onHostResume(Activity activity) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
@@ -558,19 +551,20 @@ public class ReactInstanceManager {
|
||||
// We check if activity is attached to window by checking if decor view is attached
|
||||
final View decorView = mCurrentActivity.getWindow().getDecorView();
|
||||
if (!ViewCompat.isAttachedToWindow(decorView)) {
|
||||
decorView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
// we can drop listener now that we know the view is attached
|
||||
decorView.removeOnAttachStateChangeListener(this);
|
||||
mDevSupportManager.setDevSupportEnabled(true);
|
||||
}
|
||||
decorView.addOnAttachStateChangeListener(
|
||||
new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
// we can drop listener now that we know the view is attached
|
||||
decorView.removeOnAttachStateChangeListener(this);
|
||||
mDevSupportManager.setDevSupportEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// activity is attached to window, we can enable dev support immediately
|
||||
mDevSupportManager.setDevSupportEnabled(true);
|
||||
@@ -612,9 +606,7 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy this React instance and the attached JS context.
|
||||
*/
|
||||
/** Destroy this React instance and the attached JS context. */
|
||||
@ThreadConfined(UI)
|
||||
public void destroy() {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
@@ -655,9 +647,9 @@ public class ReactInstanceManager {
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (currentContext != null) {
|
||||
// we currently don't have an onCreate callback so we call onResume for both transitions
|
||||
if (force ||
|
||||
mLifecycleState == LifecycleState.BEFORE_RESUME ||
|
||||
mLifecycleState == LifecycleState.BEFORE_CREATE) {
|
||||
if (force
|
||||
|| mLifecycleState == LifecycleState.BEFORE_RESUME
|
||||
|| mLifecycleState == LifecycleState.BEFORE_CREATE) {
|
||||
currentContext.onHostResume(mCurrentActivity);
|
||||
}
|
||||
}
|
||||
@@ -729,9 +721,9 @@ public class ReactInstanceManager {
|
||||
* Attach given {@param reactRoot} to a catalyst instance manager and start JS application using
|
||||
* JS module provided by {@link ReactRootView#getJSModuleName}. If the react context is currently
|
||||
* being (re)-created, or if react context has not been created yet, the JS application associated
|
||||
* with the provided reactRoot reactRoot will be started asynchronously, i.e this method won't block.
|
||||
* This reactRoot will then be tracked by this manager and in case of catalyst instance restart it will
|
||||
* be re-attached.
|
||||
* with the provided reactRoot reactRoot will be started asynchronously, i.e this method won't
|
||||
* block. This reactRoot will then be tracked by this manager and in case of catalyst instance
|
||||
* restart it will be re-attached.
|
||||
*/
|
||||
@ThreadConfined(UI)
|
||||
public void attachRootView(ReactRoot reactRoot) {
|
||||
@@ -742,7 +734,8 @@ public class ReactInstanceManager {
|
||||
clearReactRoot(reactRoot);
|
||||
|
||||
// If react context is being created in the background, JS application will be started
|
||||
// automatically when creation completes, as reactRoot reactRoot is part of the attached reactRoot reactRoot list.
|
||||
// automatically when creation completes, as reactRoot reactRoot is part of the attached
|
||||
// reactRoot reactRoot list.
|
||||
ReactContext currentContext = getCurrentReactContext();
|
||||
if (mCreateReactContextThread == null && currentContext != null) {
|
||||
attachRootViewToInstance(reactRoot);
|
||||
@@ -768,9 +761,7 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses configured {@link ReactPackage} instances to create all view managers.
|
||||
*/
|
||||
/** Uses configured {@link ReactPackage} instances to create all view managers. */
|
||||
public List<ViewManager> getOrCreateViewManagers(
|
||||
ReactApplicationContext catalystApplicationContext) {
|
||||
ReactMarker.logMarker(CREATE_VIEW_MANAGERS_START);
|
||||
@@ -821,7 +812,7 @@ public class ReactInstanceManager {
|
||||
public @Nullable List<String> getViewManagerNames() {
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerNames");
|
||||
ReactApplicationContext context;
|
||||
synchronized(mReactContextLock) {
|
||||
synchronized (mReactContextLock) {
|
||||
context = (ReactApplicationContext) getCurrentReactContext();
|
||||
if (context == null || !context.hasActiveCatalystInstance()) {
|
||||
return null;
|
||||
@@ -831,9 +822,10 @@ public class ReactInstanceManager {
|
||||
synchronized (mPackages) {
|
||||
Set<String> uniqueNames = new HashSet<>();
|
||||
for (ReactPackage reactPackage : mPackages) {
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerName")
|
||||
.arg("Package", reactPackage.getClass().getSimpleName())
|
||||
.flush();
|
||||
SystraceMessage.beginSection(
|
||||
TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstanceManager.getViewManagerName")
|
||||
.arg("Package", reactPackage.getClass().getSimpleName())
|
||||
.flush();
|
||||
if (reactPackage instanceof ViewManagerOnDemandReactPackage) {
|
||||
List<String> names =
|
||||
((ViewManagerOnDemandReactPackage) reactPackage).getViewManagerNames(context);
|
||||
@@ -848,16 +840,12 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to be notified of react instance events.
|
||||
*/
|
||||
/** Add a listener to be notified of react instance events. */
|
||||
public void addReactInstanceEventListener(ReactInstanceEventListener listener) {
|
||||
mReactInstanceEventListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener previously added with {@link #addReactInstanceEventListener}.
|
||||
*/
|
||||
/** Remove a listener previously added with {@link #addReactInstanceEventListener}. */
|
||||
public void removeReactInstanceEventListener(ReactInstanceEventListener listener) {
|
||||
mReactInstanceEventListeners.remove(listener);
|
||||
}
|
||||
@@ -891,26 +879,24 @@ public class ReactInstanceManager {
|
||||
private void onJSBundleLoadedFromServer(@Nullable NativeDeltaClient nativeDeltaClient) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.onJSBundleLoadedFromServer()");
|
||||
|
||||
JSBundleLoader bundleLoader = nativeDeltaClient == null
|
||||
? JSBundleLoader.createCachedBundleFromNetworkLoader(
|
||||
mDevSupportManager.getSourceUrl(),
|
||||
mDevSupportManager.getDownloadedJSBundleFile())
|
||||
: JSBundleLoader.createDeltaFromNetworkLoader(
|
||||
mDevSupportManager.getSourceUrl(), nativeDeltaClient);
|
||||
JSBundleLoader bundleLoader =
|
||||
nativeDeltaClient == null
|
||||
? JSBundleLoader.createCachedBundleFromNetworkLoader(
|
||||
mDevSupportManager.getSourceUrl(), mDevSupportManager.getDownloadedJSBundleFile())
|
||||
: JSBundleLoader.createDeltaFromNetworkLoader(
|
||||
mDevSupportManager.getSourceUrl(), nativeDeltaClient);
|
||||
|
||||
recreateReactContextInBackground(mJavaScriptExecutorFactory, bundleLoader);
|
||||
}
|
||||
|
||||
@ThreadConfined(UI)
|
||||
private void recreateReactContextInBackground(
|
||||
JavaScriptExecutorFactory jsExecutorFactory,
|
||||
JSBundleLoader jsBundleLoader) {
|
||||
JavaScriptExecutorFactory jsExecutorFactory, JSBundleLoader jsBundleLoader) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.recreateReactContextInBackground()");
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
final ReactContextInitParams initParams = new ReactContextInitParams(
|
||||
jsExecutorFactory,
|
||||
jsBundleLoader);
|
||||
final ReactContextInitParams initParams =
|
||||
new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);
|
||||
if (mCreateReactContextThread == null) {
|
||||
runCreateReactContextOnNewThread(initParams);
|
||||
} else {
|
||||
@@ -947,7 +933,8 @@ public class ReactInstanceManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
// As destroy() may have run and set this to false, ensure that it is true before we create
|
||||
// As destroy() may have run and set this to false, ensure that it is true before we
|
||||
// create
|
||||
mHasStartedCreatingInitialContext = true;
|
||||
|
||||
try {
|
||||
@@ -1009,7 +996,6 @@ public class ReactInstanceManager {
|
||||
|
||||
catalystInstance.initialize();
|
||||
|
||||
|
||||
mDevSupportManager.onNewReactContextCreated(reactContext);
|
||||
mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
|
||||
moveReactContextToCurrentLifecycleState();
|
||||
@@ -1022,7 +1008,7 @@ public class ReactInstanceManager {
|
||||
}
|
||||
|
||||
ReactInstanceEventListener[] listeners =
|
||||
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
|
||||
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
|
||||
final ReactInstanceEventListener[] finalListeners =
|
||||
mReactInstanceEventListeners.toArray(listeners);
|
||||
|
||||
@@ -1057,28 +1043,30 @@ public class ReactInstanceManager {
|
||||
private void attachRootViewToInstance(final ReactRoot reactRoot) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.attachRootViewToInstance()");
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachRootViewToInstance");
|
||||
UIManager uiManager = UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
|
||||
UIManager uiManager =
|
||||
UIManagerHelper.getUIManager(mCurrentReactContext, reactRoot.getUIManagerType());
|
||||
|
||||
@Nullable Bundle initialProperties = reactRoot.getAppProperties();
|
||||
|
||||
final int rootTag = uiManager.addRootView(
|
||||
reactRoot.getRootViewGroup(),
|
||||
initialProperties == null ?
|
||||
new WritableNativeMap() : Arguments.fromBundle(initialProperties),
|
||||
reactRoot.getInitialUITemplate());
|
||||
final int rootTag =
|
||||
uiManager.addRootView(
|
||||
reactRoot.getRootViewGroup(),
|
||||
initialProperties == null
|
||||
? new WritableNativeMap()
|
||||
: Arguments.fromBundle(initialProperties),
|
||||
reactRoot.getInitialUITemplate());
|
||||
reactRoot.setRootViewTag(rootTag);
|
||||
if (reactRoot.getUIManagerType() == FABRIC) {
|
||||
// Fabric requires to call updateRootLayoutSpecs before starting JS Application,
|
||||
// this ensures the root will hace the correct pointScaleFactor.
|
||||
uiManager.updateRootLayoutSpecs(rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
|
||||
uiManager.updateRootLayoutSpecs(
|
||||
rootTag, reactRoot.getWidthMeasureSpec(), reactRoot.getHeightMeasureSpec());
|
||||
reactRoot.setShouldLogContentAppeared(true);
|
||||
} else {
|
||||
reactRoot.runApplication();
|
||||
}
|
||||
Systrace.beginAsyncSection(
|
||||
TRACE_TAG_REACT_JAVA_BRIDGE,
|
||||
"pre_rootView.onAttachedToReactInstance",
|
||||
rootTag);
|
||||
TRACE_TAG_REACT_JAVA_BRIDGE, "pre_rootView.onAttachedToReactInstance", rootTag);
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
@@ -1091,19 +1079,18 @@ public class ReactInstanceManager {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
|
||||
private void detachViewFromInstance(
|
||||
ReactRoot reactRoot,
|
||||
CatalystInstance catalystInstance) {
|
||||
private void detachViewFromInstance(ReactRoot reactRoot, CatalystInstance catalystInstance) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.detachViewFromInstance()");
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (reactRoot.getUIManagerType() == FABRIC) {
|
||||
catalystInstance.getJSModule(ReactFabric.class)
|
||||
.unmountComponentAtNode(reactRoot.getRootViewTag());
|
||||
catalystInstance
|
||||
.getJSModule(ReactFabric.class)
|
||||
.unmountComponentAtNode(reactRoot.getRootViewTag());
|
||||
} else {
|
||||
catalystInstance.getJSModule(AppRegistry.class)
|
||||
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
|
||||
catalystInstance
|
||||
.getJSModule(AppRegistry.class)
|
||||
.unmountApplicationComponentAtRootTag(reactRoot.getRootViewTag());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void tearDownReactContext(ReactContext reactContext) {
|
||||
@@ -1124,29 +1111,28 @@ public class ReactInstanceManager {
|
||||
mMemoryPressureRouter.removeMemoryPressureListener(reactContext.getCatalystInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
|
||||
*/
|
||||
/** @return instance of {@link ReactContext} configured a {@link CatalystInstance} set */
|
||||
private ReactApplicationContext createReactContext(
|
||||
JavaScriptExecutor jsExecutor,
|
||||
JSBundleLoader jsBundleLoader) {
|
||||
JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
|
||||
Log.d(ReactConstants.TAG, "ReactInstanceManager.createReactContext()");
|
||||
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
|
||||
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
|
||||
|
||||
NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
|
||||
? mNativeModuleCallExceptionHandler
|
||||
: mDevSupportManager;
|
||||
NativeModuleCallExceptionHandler exceptionHandler =
|
||||
mNativeModuleCallExceptionHandler != null
|
||||
? mNativeModuleCallExceptionHandler
|
||||
: mDevSupportManager;
|
||||
reactContext.setNativeModuleCallExceptionHandler(exceptionHandler);
|
||||
|
||||
NativeModuleRegistry nativeModuleRegistry = processPackages(reactContext, mPackages, false);
|
||||
|
||||
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
|
||||
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
|
||||
.setJSExecutor(jsExecutor)
|
||||
.setRegistry(nativeModuleRegistry)
|
||||
.setJSBundleLoader(jsBundleLoader)
|
||||
.setNativeModuleCallExceptionHandler(exceptionHandler);
|
||||
CatalystInstanceImpl.Builder catalystInstanceBuilder =
|
||||
new CatalystInstanceImpl.Builder()
|
||||
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
|
||||
.setJSExecutor(jsExecutor)
|
||||
.setRegistry(nativeModuleRegistry)
|
||||
.setJSBundleLoader(jsBundleLoader)
|
||||
.setNativeModuleCallExceptionHandler(exceptionHandler);
|
||||
|
||||
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
|
||||
// CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
|
||||
@@ -1162,11 +1148,13 @@ public class ReactInstanceManager {
|
||||
reactContext.initializeWithInstance(catalystInstance);
|
||||
|
||||
if (mJSIModulePackage != null) {
|
||||
catalystInstance.addJSIModules(mJSIModulePackage
|
||||
.getJSIModules(reactContext, catalystInstance.getJavaScriptContextHolder()));
|
||||
catalystInstance.addJSIModules(
|
||||
mJSIModulePackage.getJSIModules(
|
||||
reactContext, catalystInstance.getJavaScriptContextHolder()));
|
||||
|
||||
if (ReactFeatureFlags.useTurboModules) {
|
||||
catalystInstance.setTurboModuleManager(catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager));
|
||||
catalystInstance.setTurboModuleManager(
|
||||
catalystInstance.getJSIModule(JSIModuleType.TurboModuleManager));
|
||||
}
|
||||
}
|
||||
if (mBridgeIdleDebugListener != null) {
|
||||
@@ -1184,12 +1172,11 @@ public class ReactInstanceManager {
|
||||
}
|
||||
|
||||
private NativeModuleRegistry processPackages(
|
||||
ReactApplicationContext reactContext,
|
||||
List<ReactPackage> packages,
|
||||
boolean checkAndUpdatePackageMembership) {
|
||||
NativeModuleRegistryBuilder nativeModuleRegistryBuilder = new NativeModuleRegistryBuilder(
|
||||
reactContext,
|
||||
this);
|
||||
ReactApplicationContext reactContext,
|
||||
List<ReactPackage> packages,
|
||||
boolean checkAndUpdatePackageMembership) {
|
||||
NativeModuleRegistryBuilder nativeModuleRegistryBuilder =
|
||||
new NativeModuleRegistryBuilder(reactContext, this);
|
||||
|
||||
ReactMarker.logMarker(PROCESS_PACKAGES_START);
|
||||
|
||||
@@ -1226,11 +1213,10 @@ public class ReactInstanceManager {
|
||||
}
|
||||
|
||||
private void processPackage(
|
||||
ReactPackage reactPackage,
|
||||
NativeModuleRegistryBuilder nativeModuleRegistryBuilder) {
|
||||
ReactPackage reactPackage, NativeModuleRegistryBuilder nativeModuleRegistryBuilder) {
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processPackage")
|
||||
.arg("className", reactPackage.getClass().getSimpleName())
|
||||
.flush();
|
||||
.arg("className", reactPackage.getClass().getSimpleName())
|
||||
.flush();
|
||||
if (reactPackage instanceof ReactPackageLogger) {
|
||||
((ReactPackageLogger) reactPackage).startProcessPackage();
|
||||
}
|
||||
|
||||
@@ -28,9 +28,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Builder class for {@link ReactInstanceManager}
|
||||
*/
|
||||
/** Builder class for {@link ReactInstanceManager} */
|
||||
public class ReactInstanceManagerBuilder {
|
||||
|
||||
private final List<ReactPackage> mPackages = new ArrayList<>();
|
||||
@@ -55,37 +53,31 @@ public class ReactInstanceManagerBuilder {
|
||||
private @Nullable JSIModulePackage mJSIModulesPackage;
|
||||
private @Nullable Map<String, RequestHandler> mCustomPackagerCommandHandlers;
|
||||
|
||||
/* package protected */ ReactInstanceManagerBuilder() {
|
||||
}
|
||||
/* package protected */ ReactInstanceManagerBuilder() {}
|
||||
|
||||
/**
|
||||
* Sets a provider of {@link UIImplementation}.
|
||||
* Uses default provider if null is passed.
|
||||
*/
|
||||
/** Sets a provider of {@link UIImplementation}. Uses default provider if null is passed. */
|
||||
public ReactInstanceManagerBuilder setUIImplementationProvider(
|
||||
@Nullable UIImplementationProvider uiImplementationProvider) {
|
||||
@Nullable UIImplementationProvider uiImplementationProvider) {
|
||||
mUIImplementationProvider = uiImplementationProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactInstanceManagerBuilder setJSIModulesPackage(
|
||||
@Nullable JSIModulePackage jsiModulePackage) {
|
||||
@Nullable JSIModulePackage jsiModulePackage) {
|
||||
mJSIModulesPackage = jsiModulePackage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for desired implementation of JavaScriptExecutor.
|
||||
*/
|
||||
/** Factory for desired implementation of JavaScriptExecutor. */
|
||||
public ReactInstanceManagerBuilder setJavaScriptExecutorFactory(
|
||||
@Nullable JavaScriptExecutorFactory javaScriptExecutorFactory) {
|
||||
@Nullable JavaScriptExecutorFactory javaScriptExecutorFactory) {
|
||||
mJavaScriptExecutorFactory = javaScriptExecutorFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the JS bundle file to be loaded from application's raw assets.
|
||||
* Example: {@code "index.android.js"}
|
||||
* Name of the JS bundle file to be loaded from application's raw assets. Example: {@code
|
||||
* "index.android.js"}
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setBundleAssetName(String bundleAssetName) {
|
||||
mJSBundleAssetUrl = (bundleAssetName == null ? null : "assets://" + bundleAssetName);
|
||||
@@ -96,7 +88,7 @@ public class ReactInstanceManagerBuilder {
|
||||
/**
|
||||
* Path to the JS bundle file to be loaded from the file system.
|
||||
*
|
||||
* Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
|
||||
* <p>Example: {@code "assets://index.android.js" or "/sdcard/main.jsbundle"}
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setJSBundleFile(String jsBundleFile) {
|
||||
if (jsBundleFile.startsWith("assets://")) {
|
||||
@@ -108,10 +100,10 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bundle loader to use when setting up JS environment. This supersedes
|
||||
* prior invocations of {@link setJSBundleFile} and {@link setBundleAssetName}.
|
||||
* Bundle loader to use when setting up JS environment. This supersedes prior invocations of
|
||||
* {@link setJSBundleFile} and {@link setBundleAssetName}.
|
||||
*
|
||||
* Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
|
||||
* <p>Example: {@code JSBundleLoader.createFileLoader(application, bundleFile)}
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setJSBundleLoader(JSBundleLoader jsBundleLoader) {
|
||||
mJSBundleLoader = jsBundleLoader;
|
||||
@@ -120,12 +112,9 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to your app's main module on the packager server. This is used when
|
||||
* reloading JS during development. All paths are relative to the root folder
|
||||
* the packager is serving files from.
|
||||
* Examples:
|
||||
* {@code "index.android"} or
|
||||
* {@code "subdirectory/index.android"}
|
||||
* Path to your app's main module on the packager server. This is used when reloading JS during
|
||||
* development. All paths are relative to the root folder the packager is serving files from.
|
||||
* Examples: {@code "index.android"} or {@code "subdirectory/index.android"}
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setJSMainModulePath(String jsMainModulePath) {
|
||||
mJSMainModulePath = jsMainModulePath;
|
||||
@@ -143,14 +132,12 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
public ReactInstanceManagerBuilder setBridgeIdleDebugListener(
|
||||
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
|
||||
NotThreadSafeBridgeIdleDebugListener bridgeIdleDebugListener) {
|
||||
mBridgeIdleDebugListener = bridgeIdleDebugListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required. This must be your {@code Application} instance.
|
||||
*/
|
||||
/** Required. This must be your {@code Application} instance. */
|
||||
public ReactInstanceManagerBuilder setApplication(Application application) {
|
||||
mApplication = application;
|
||||
return this;
|
||||
@@ -162,15 +149,15 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
public ReactInstanceManagerBuilder setDefaultHardwareBackBtnHandler(
|
||||
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
|
||||
DefaultHardwareBackBtnHandler defaultHardwareBackBtnHandler) {
|
||||
mDefaultHardwareBackBtnHandler = defaultHardwareBackBtnHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@code true}, developer options such as JS reloading and debugging are enabled.
|
||||
* Note you still have to call {@link #showDevOptionsDialog} to show the dev menu,
|
||||
* e.g. when the device Menu button is pressed.
|
||||
* When {@code true}, developer options such as JS reloading and debugging are enabled. Note you
|
||||
* still have to call {@link #showDevOptionsDialog} to show the dev menu, e.g. when the device
|
||||
* Menu button is pressed.
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setUseDeveloperSupport(boolean useDeveloperSupport) {
|
||||
mUseDeveloperSupport = useDeveloperSupport;
|
||||
@@ -182,18 +169,18 @@ public class ReactInstanceManagerBuilder {
|
||||
* creation time, we wouldn't expect an onResume call until we get an onPause call.
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setInitialLifecycleState(
|
||||
LifecycleState initialLifecycleState) {
|
||||
LifecycleState initialLifecycleState) {
|
||||
mInitialLifecycleState = initialLifecycleState;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exception handler for all native module calls. If not set, the default
|
||||
* {@link DevSupportManager} will be used, which shows a redbox in dev mode and rethrows
|
||||
* (crashes the app) in prod mode.
|
||||
* Set the exception handler for all native module calls. If not set, the default {@link
|
||||
* DevSupportManager} will be used, which shows a redbox in dev mode and rethrows (crashes the
|
||||
* app) in prod mode.
|
||||
*/
|
||||
public ReactInstanceManagerBuilder setNativeModuleCallExceptionHandler(
|
||||
NativeModuleCallExceptionHandler handler) {
|
||||
NativeModuleCallExceptionHandler handler) {
|
||||
mNativeModuleCallExceptionHandler = handler;
|
||||
return this;
|
||||
}
|
||||
@@ -209,7 +196,7 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
public ReactInstanceManagerBuilder setDevBundleDownloadListener(
|
||||
@Nullable DevBundleDownloadListener listener) {
|
||||
@Nullable DevBundleDownloadListener listener) {
|
||||
mDevBundleDownloadListener = listener;
|
||||
return this;
|
||||
}
|
||||
@@ -232,33 +219,32 @@ public class ReactInstanceManagerBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new {@link ReactInstanceManager}.
|
||||
* Before calling {@code build}, the following must be called:
|
||||
* Instantiates a new {@link ReactInstanceManager}. Before calling {@code build}, the following
|
||||
* must be called:
|
||||
*
|
||||
* <ul>
|
||||
* <li> {@link #setApplication}
|
||||
* <li> {@link #setCurrentActivity} if the activity has already resumed
|
||||
* <li> {@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
|
||||
* <li> {@link #setJSBundleFile} or {@link #setJSMainModulePath}
|
||||
* <li>{@link #setApplication}
|
||||
* <li>{@link #setCurrentActivity} if the activity has already resumed
|
||||
* <li>{@link #setDefaultHardwareBackBtnHandler} if the activity has already resumed
|
||||
* <li>{@link #setJSBundleFile} or {@link #setJSMainModulePath}
|
||||
* </ul>
|
||||
*/
|
||||
public ReactInstanceManager build() {
|
||||
Assertions.assertNotNull(
|
||||
mApplication,
|
||||
"Application property has not been set with this builder");
|
||||
mApplication, "Application property has not been set with this builder");
|
||||
|
||||
if (mInitialLifecycleState == LifecycleState.RESUMED) {
|
||||
Assertions.assertNotNull(
|
||||
mCurrentActivity,
|
||||
"Activity needs to be set if initial lifecycle state is resumed");
|
||||
mCurrentActivity, "Activity needs to be set if initial lifecycle state is resumed");
|
||||
}
|
||||
|
||||
Assertions.assertCondition(
|
||||
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
|
||||
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
|
||||
mUseDeveloperSupport || mJSBundleAssetUrl != null || mJSBundleLoader != null,
|
||||
"JS Bundle File or Asset URL has to be provided when dev support is disabled");
|
||||
|
||||
Assertions.assertCondition(
|
||||
mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null,
|
||||
"Either MainModulePath or JS Bundle File needs to be provided");
|
||||
mJSMainModulePath != null || mJSBundleAssetUrl != null || mJSBundleLoader != null,
|
||||
"Either MainModulePath or JS Bundle File needs to be provided");
|
||||
|
||||
if (mUIImplementationProvider == null) {
|
||||
// create default UIImplementationProvider if the provided one is null.
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A simple wrapper for ReactPackage to make it aware of its {@link ReactInstanceManager}
|
||||
* when creating native modules. This is useful when the package needs to ask
|
||||
* the instance manager for more information, like {@link DevSupportManager}.
|
||||
* A simple wrapper for ReactPackage to make it aware of its {@link ReactInstanceManager} when
|
||||
* creating native modules. This is useful when the package needs to ask the instance manager for
|
||||
* more information, like {@link DevSupportManager}.
|
||||
*
|
||||
* TODO(t11394819): Consolidate this with LazyReactPackage
|
||||
* Use {@link ReactPackage} or {@link LazyReactPackage} and inject reactInstanceManager as a part of when plugins are initialized.
|
||||
* <p>TODO(t11394819): Consolidate this with LazyReactPackage Use {@link ReactPackage} or {@link
|
||||
* LazyReactPackage} and inject reactInstanceManager as a part of when plugins are initialized.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class ReactInstancePackage implements ReactPackage {
|
||||
|
||||
public abstract List<NativeModule> createNativeModules(
|
||||
ReactApplicationContext reactContext,
|
||||
ReactInstanceManager reactInstanceManager);
|
||||
ReactApplicationContext reactContext, ReactInstanceManager reactInstanceManager);
|
||||
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import android.app.Application;
|
||||
@@ -32,9 +31,7 @@ public abstract class ReactNativeHost {
|
||||
mApplication = application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current {@link ReactInstanceManager} instance, or create one.
|
||||
*/
|
||||
/** Get the current {@link ReactInstanceManager} instance, or create one. */
|
||||
public ReactInstanceManager getReactInstanceManager() {
|
||||
if (mReactInstanceManager == null) {
|
||||
ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START);
|
||||
@@ -65,15 +62,16 @@ public abstract class ReactNativeHost {
|
||||
|
||||
protected ReactInstanceManager createReactInstanceManager() {
|
||||
ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
|
||||
ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
|
||||
.setApplication(mApplication)
|
||||
.setJSMainModulePath(getJSMainModuleName())
|
||||
.setUseDeveloperSupport(getUseDeveloperSupport())
|
||||
.setRedBoxHandler(getRedBoxHandler())
|
||||
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
|
||||
.setUIImplementationProvider(getUIImplementationProvider())
|
||||
.setJSIModulesPackage(getJSIModulePackage())
|
||||
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
|
||||
ReactInstanceManagerBuilder builder =
|
||||
ReactInstanceManager.builder()
|
||||
.setApplication(mApplication)
|
||||
.setJSMainModulePath(getJSMainModuleName())
|
||||
.setUseDeveloperSupport(getUseDeveloperSupport())
|
||||
.setRedBoxHandler(getRedBoxHandler())
|
||||
.setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
|
||||
.setUIImplementationProvider(getUIImplementationProvider())
|
||||
.setJSIModulesPackage(getJSIModulePackage())
|
||||
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
|
||||
|
||||
for (ReactPackage reactPackage : getPackages()) {
|
||||
builder.addPackage(reactPackage);
|
||||
@@ -90,17 +88,12 @@ public abstract class ReactNativeHost {
|
||||
return reactInstanceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link RedBoxHandler} to send RedBox-related callbacks to.
|
||||
*/
|
||||
/** Get the {@link RedBoxHandler} to send RedBox-related callbacks to. */
|
||||
protected @Nullable RedBoxHandler getRedBoxHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link JavaScriptExecutorFactory}. Override this to use a custom
|
||||
* Executor.
|
||||
*/
|
||||
/** Get the {@link JavaScriptExecutorFactory}. Override this to use a custom Executor. */
|
||||
protected @Nullable JavaScriptExecutorFactory getJavaScriptExecutorFactory() {
|
||||
return null;
|
||||
}
|
||||
@@ -113,22 +106,20 @@ public abstract class ReactNativeHost {
|
||||
* Get the {@link UIImplementationProvider} to use. Override this method if you want to use a
|
||||
* custom UI implementation.
|
||||
*
|
||||
* Note: this is very advanced functionality, in 99% of cases you don't need to override this.
|
||||
* <p>Note: this is very advanced functionality, in 99% of cases you don't need to override this.
|
||||
*/
|
||||
protected UIImplementationProvider getUIImplementationProvider() {
|
||||
return new UIImplementationProvider();
|
||||
}
|
||||
|
||||
protected @Nullable
|
||||
JSIModulePackage getJSIModulePackage() {
|
||||
protected @Nullable JSIModulePackage getJSIModulePackage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the main module. Determines the URL used to fetch the JS bundle
|
||||
* from the packager server. It is only used when dev support is enabled.
|
||||
* This is the first file to be executed once the {@link ReactInstanceManager} is created.
|
||||
* e.g. "index.android"
|
||||
* Returns the name of the main module. Determines the URL used to fetch the JS bundle from the
|
||||
* packager server. It is only used when dev support is enabled. This is the first file to be
|
||||
* executed once the {@link ReactInstanceManager} is created. e.g. "index.android"
|
||||
*/
|
||||
protected String getJSMainModuleName() {
|
||||
return "index.android";
|
||||
@@ -136,9 +127,8 @@ public abstract class ReactNativeHost {
|
||||
|
||||
/**
|
||||
* Returns a custom path of the bundle file. This is used in cases the bundle should be loaded
|
||||
* from a custom path. By default it is loaded from Android assets, from a path specified
|
||||
* by {@link getBundleAssetName}.
|
||||
* e.g. "file://sdcard/myapp_cache/index.android.bundle"
|
||||
* from a custom path. By default it is loaded from Android assets, from a path specified by
|
||||
* {@link getBundleAssetName}. e.g. "file://sdcard/myapp_cache/index.android.bundle"
|
||||
*/
|
||||
protected @Nullable String getJSBundleFile() {
|
||||
return null;
|
||||
@@ -146,24 +136,20 @@ public abstract class ReactNativeHost {
|
||||
|
||||
/**
|
||||
* Returns the name of the bundle in assets. If this is null, and no file path is specified for
|
||||
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will
|
||||
* always try to load the JS bundle from the packager server.
|
||||
* e.g. "index.android.bundle"
|
||||
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will always
|
||||
* try to load the JS bundle from the packager server. e.g. "index.android.bundle"
|
||||
*/
|
||||
protected @Nullable String getBundleAssetName() {
|
||||
return "index.android.bundle";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether dev mode should be enabled. This enables e.g. the dev menu.
|
||||
*/
|
||||
/** Returns whether dev mode should be enabled. This enables e.g. the dev menu. */
|
||||
public abstract boolean getUseDeveloperSupport();
|
||||
|
||||
/**
|
||||
* Returns a list of {@link ReactPackage} used by the app.
|
||||
* You'll most likely want to return at least the {@code MainReactPackage}.
|
||||
* If your app uses additional views or modules besides the default ones,
|
||||
* you'll want to include more packages here.
|
||||
* Returns a list of {@link ReactPackage} used by the app. You'll most likely want to return at
|
||||
* least the {@code MainReactPackage}. If your app uses additional views or modules besides the
|
||||
* default ones, you'll want to include more packages here.
|
||||
*/
|
||||
protected abstract List<ReactPackage> getPackages();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
@@ -12,21 +11,18 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Main interface for providing additional capabilities to the catalyst framework by couple of
|
||||
* different means:
|
||||
* 1) Registering new native modules
|
||||
* 2) Registering new JS modules that may be accessed from native modules or from other parts of the
|
||||
* native code (requiring JS modules from the package doesn't mean it will automatically be included
|
||||
* as a part of the JS bundle, so there should be a corresponding piece of code on JS side that will
|
||||
* require implementation of that JS module so that it gets bundled)
|
||||
* 3) Registering custom native views (view managers) and custom event types
|
||||
* 4) Registering natively packaged assets/resources (e.g. images) exposed to JS
|
||||
* different means: 1) Registering new native modules 2) Registering new JS modules that may be
|
||||
* accessed from native modules or from other parts of the native code (requiring JS modules from
|
||||
* the package doesn't mean it will automatically be included as a part of the JS bundle, so there
|
||||
* should be a corresponding piece of code on JS side that will require implementation of that JS
|
||||
* module so that it gets bundled) 3) Registering custom native views (view managers) and custom
|
||||
* event types 4) Registering natively packaged assets/resources (e.g. images) exposed to JS
|
||||
*
|
||||
* TODO(6788500, 6788507): Implement support for adding custom views, events and resources
|
||||
* <p>TODO(6788500, 6788507): Implement support for adding custom views, events and resources
|
||||
*/
|
||||
public interface ReactPackage {
|
||||
|
||||
@@ -37,9 +33,7 @@ public interface ReactPackage {
|
||||
@Nonnull
|
||||
List<NativeModule> createNativeModules(@Nonnull ReactApplicationContext reactContext);
|
||||
|
||||
/**
|
||||
* @return a list of view managers that should be registered with {@link UIManagerModule}
|
||||
*/
|
||||
/** @return a list of view managers that should be registered with {@link UIManagerModule} */
|
||||
@Nonnull
|
||||
List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
|
||||
package com.facebook.react;
|
||||
|
||||
/**
|
||||
* Interface for the bridge to call for TTI start and end markers.
|
||||
*/
|
||||
/** Interface for the bridge to call for TTI start and end markers. */
|
||||
public interface ReactPackageLogger {
|
||||
|
||||
void startProcessPackage();
|
||||
|
||||
void endProcessPackage();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT;
|
||||
@@ -46,8 +45,8 @@ import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.JSTouchDispatcher;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.RootView;
|
||||
import com.facebook.react.uimanager.ReactRoot;
|
||||
import com.facebook.react.uimanager.RootView;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.common.UIManagerType;
|
||||
@@ -62,20 +61,16 @@ import javax.annotation.Nullable;
|
||||
* ViewGroup#onInterceptTouchEvent} method in order to be notified about the events for all of its
|
||||
* children and it's also overriding {@link ViewGroup#requestDisallowInterceptTouchEvent} to make
|
||||
* sure that {@link ViewGroup#onInterceptTouchEvent} will get events even when some child view start
|
||||
* intercepting it. In case when no child view is interested in handling some particular touch event,
|
||||
* this view's {@link View#onTouchEvent} will still return true in order to be notified about all
|
||||
* subsequent touch events related to that gesture (in case when JS code wants to handle that
|
||||
* intercepting it. In case when no child view is interested in handling some particular touch
|
||||
* event, this view's {@link View#onTouchEvent} will still return true in order to be notified about
|
||||
* all subsequent touch events related to that gesture (in case when JS code wants to handle that
|
||||
* gesture).
|
||||
*/
|
||||
public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
/**
|
||||
* Listener interface for react root view events
|
||||
*/
|
||||
/** Listener interface for react root view events */
|
||||
public interface ReactRootViewEventListener {
|
||||
/**
|
||||
* Called when the react context is attached to a ReactRootView.
|
||||
*/
|
||||
/** Called when the react context is attached to a ReactRootView. */
|
||||
void onAttachedToReactInstance(ReactRootView rootView);
|
||||
}
|
||||
|
||||
@@ -89,7 +84,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
private boolean mIsAttachedToInstance;
|
||||
private boolean mShouldLogContentAppeared;
|
||||
private @Nullable JSTouchDispatcher mJSTouchDispatcher;
|
||||
private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper = new ReactAndroidHWInputDeviceHelper(this);
|
||||
private final ReactAndroidHWInputDeviceHelper mAndroidHWInputDeviceHelper =
|
||||
new ReactAndroidHWInputDeviceHelper(this);
|
||||
private boolean mWasMeasured = false;
|
||||
private int mWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
|
||||
private int mHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
|
||||
@@ -135,8 +131,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.onMeasure");
|
||||
try {
|
||||
boolean measureSpecsUpdated = widthMeasureSpec != mWidthMeasureSpec ||
|
||||
heightMeasureSpec != mHeightMeasureSpec;
|
||||
boolean measureSpecsUpdated =
|
||||
widthMeasureSpec != mWidthMeasureSpec || heightMeasureSpec != mHeightMeasureSpec;
|
||||
mWidthMeasureSpec = widthMeasureSpec;
|
||||
mHeightMeasureSpec = heightMeasureSpec;
|
||||
|
||||
@@ -189,21 +185,22 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public void onChildStartedNativeGesture(MotionEvent androidEvent) {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
|
||||
return;
|
||||
}
|
||||
if (mJSTouchDispatcher == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS before the dispatcher is available");
|
||||
ReactConstants.TAG, "Unable to dispatch touch to JS before the dispatcher is available");
|
||||
return;
|
||||
}
|
||||
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
||||
EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
EventDispatcher eventDispatcher =
|
||||
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
mJSTouchDispatcher.onChildStartedNativeGesture(androidEvent, eventDispatcher);
|
||||
}
|
||||
|
||||
@@ -235,11 +232,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent ev) {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle key event as the catalyst instance has not been attached");
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle key event as the catalyst instance has not been attached");
|
||||
return super.dispatchKeyEvent(ev);
|
||||
}
|
||||
mAndroidHWInputDeviceHelper.handleKeyEvent(ev);
|
||||
@@ -248,11 +246,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle focus changed event as the catalyst instance has not been attached");
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle focus changed event as the catalyst instance has not been attached");
|
||||
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
|
||||
return;
|
||||
}
|
||||
@@ -262,11 +261,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public void requestChildFocus(View child, View focused) {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle child focus changed event as the catalyst instance has not been attached");
|
||||
ReactConstants.TAG,
|
||||
"Unable to handle child focus changed event as the catalyst instance has not been attached");
|
||||
super.requestChildFocus(child, focused);
|
||||
return;
|
||||
}
|
||||
@@ -275,21 +275,22 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
}
|
||||
|
||||
private void dispatchJSTouchEvent(MotionEvent event) {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS as the catalyst instance has not been attached");
|
||||
return;
|
||||
}
|
||||
if (mJSTouchDispatcher == null) {
|
||||
FLog.w(
|
||||
ReactConstants.TAG,
|
||||
"Unable to dispatch touch to JS before the dispatcher is available");
|
||||
ReactConstants.TAG, "Unable to dispatch touch to JS before the dispatcher is available");
|
||||
return;
|
||||
}
|
||||
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
||||
EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
EventDispatcher eventDispatcher =
|
||||
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher);
|
||||
}
|
||||
|
||||
@@ -349,24 +350,23 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle)}
|
||||
*/
|
||||
/** {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle)} */
|
||||
public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName) {
|
||||
startReactApplication(reactInstanceManager, moduleName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle, String)}
|
||||
*/
|
||||
public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle initialProperties) {
|
||||
/** {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle, String)} */
|
||||
public void startReactApplication(
|
||||
ReactInstanceManager reactInstanceManager,
|
||||
String moduleName,
|
||||
@Nullable Bundle initialProperties) {
|
||||
startReactApplication(reactInstanceManager, moduleName, initialProperties, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule rendering of the react component rendered by the JS application from the given JS
|
||||
* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the
|
||||
* JS context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
|
||||
* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the JS
|
||||
* context of that manager. Extra parameter {@param launchOptions} can be used to pass initial
|
||||
* properties for the react component.
|
||||
*/
|
||||
public void startReactApplication(
|
||||
@@ -382,8 +382,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
// here as it may be deallocated in native after passing via JNI bridge, but we want to reuse
|
||||
// it in the case of re-creating the catalyst instance
|
||||
Assertions.assertCondition(
|
||||
mReactInstanceManager == null,
|
||||
"This root view has already been attached to a catalyst instance manager");
|
||||
mReactInstanceManager == null,
|
||||
"This root view has already been attached to a catalyst instance manager");
|
||||
|
||||
mReactInstanceManager = reactInstanceManager;
|
||||
mJSModuleName = moduleName;
|
||||
@@ -429,7 +429,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
if (reactApplicationContext != null) {
|
||||
UIManagerHelper.getUIManager(reactApplicationContext, getUIManagerType())
|
||||
.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
|
||||
.updateRootLayoutSpecs(getRootViewTag(), widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public void onStage(int stage) {
|
||||
switch(stage) {
|
||||
switch (stage) {
|
||||
case ReactStage.ON_ATTACH_TO_INSTANCE:
|
||||
onAttachedToReactInstance();
|
||||
break;
|
||||
@@ -498,51 +498,51 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls into JS to start the React application. Can be called multiple times with the
|
||||
* same rootTag, which will re-render the application from the root.
|
||||
* Calls into JS to start the React application. Can be called multiple times with the same
|
||||
* rootTag, which will re-render the application from the root.
|
||||
*/
|
||||
@Override
|
||||
public void runApplication() {
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
|
||||
try {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CatalystInstance catalystInstance = reactContext.getCatalystInstance();
|
||||
String jsAppModuleName = getJSModuleName();
|
||||
|
||||
if (mUseSurface) {
|
||||
// TODO call surface's runApplication
|
||||
} else {
|
||||
if (mWasMeasured) {
|
||||
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
|
||||
}
|
||||
|
||||
WritableNativeMap appParams = new WritableNativeMap();
|
||||
appParams.putDouble("rootTag", getRootViewTag());
|
||||
@Nullable Bundle appProperties = getAppProperties();
|
||||
if (appProperties != null) {
|
||||
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
|
||||
}
|
||||
|
||||
mShouldLogContentAppeared = true;
|
||||
|
||||
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
|
||||
}
|
||||
} finally {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "ReactRootView.runApplication");
|
||||
try {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReactContext reactContext = mReactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CatalystInstance catalystInstance = reactContext.getCatalystInstance();
|
||||
String jsAppModuleName = getJSModuleName();
|
||||
|
||||
if (mUseSurface) {
|
||||
// TODO call surface's runApplication
|
||||
} else {
|
||||
if (mWasMeasured) {
|
||||
updateRootLayoutSpecs(mWidthMeasureSpec, mHeightMeasureSpec);
|
||||
}
|
||||
|
||||
WritableNativeMap appParams = new WritableNativeMap();
|
||||
appParams.putDouble("rootTag", getRootViewTag());
|
||||
@Nullable Bundle appProperties = getAppProperties();
|
||||
if (appProperties != null) {
|
||||
appParams.putMap("initialProps", Arguments.fromBundle(appProperties));
|
||||
}
|
||||
|
||||
mShouldLogContentAppeared = true;
|
||||
|
||||
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
|
||||
}
|
||||
} finally {
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is used by unit test to setup mIsAttachedToWindow flags, that will let this
|
||||
* view to be properly attached to catalyst instance by startReactApplication call
|
||||
* Is used by unit test to setup mIsAttachedToWindow flags, that will let this view to be properly
|
||||
* attached to catalyst instance by startReactApplication call
|
||||
*/
|
||||
@VisibleForTesting
|
||||
/* package */ void simulateAttachForTesting() {
|
||||
@@ -576,12 +576,12 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
Assertions.assertCondition(
|
||||
!mIsAttachedToInstance,
|
||||
"The application this ReactRootView was rendering was not unmounted before the " +
|
||||
"ReactRootView was garbage collected. This usually means that your application is " +
|
||||
"leaking large amounts of memory. To solve this, make sure to call " +
|
||||
"ReactRootView#unmountReactApplication in the onDestroy() of your hosting Activity or in " +
|
||||
"the onDestroyView() of your hosting Fragment.");
|
||||
!mIsAttachedToInstance,
|
||||
"The application this ReactRootView was rendering was not unmounted before the "
|
||||
+ "ReactRootView was garbage collected. This usually means that your application is "
|
||||
+ "leaking large amounts of memory. To solve this, make sure to call "
|
||||
+ "ReactRootView#unmountReactApplication in the onDestroy() of your hosting Activity or in "
|
||||
+ "the onDestroyView() of your hosting Fragment.");
|
||||
}
|
||||
|
||||
public int getRootViewTag() {
|
||||
@@ -594,9 +594,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public void handleException(final Throwable t) {
|
||||
if (mReactInstanceManager == null
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
throw new RuntimeException(t);
|
||||
if (mReactInstanceManager == null || mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
|
||||
Exception e = new IllegalViewOperationException(t.getMessage(), this, t);
|
||||
@@ -619,9 +618,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
/* package */ void sendEvent(String eventName, @Nullable WritableMap params) {
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.getCurrentReactContext()
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(eventName, params);
|
||||
mReactInstanceManager
|
||||
.getCurrentReactContext()
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit(eventName, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,8 +642,9 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (mReactInstanceManager == null || !mIsAttachedToInstance ||
|
||||
mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
if (mReactInstanceManager == null
|
||||
|| !mIsAttachedToInstance
|
||||
|| mReactInstanceManager.getCurrentReactContext() == null) {
|
||||
return;
|
||||
}
|
||||
checkForKeyboardEvents();
|
||||
@@ -654,41 +655,40 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
private void checkForKeyboardEvents() {
|
||||
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
|
||||
final int heightDiff =
|
||||
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
|
||||
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
|
||||
|
||||
boolean isKeyboardShowingOrKeyboardHeightChanged =
|
||||
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;
|
||||
mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected;
|
||||
if (isKeyboardShowingOrKeyboardHeightChanged) {
|
||||
mKeyboardHeight = heightDiff;
|
||||
sendEvent("keyboardDidShow",
|
||||
createKeyboardEventPayload(
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom),
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
|
||||
PixelUtil.toDIPFromPixel(mKeyboardHeight))
|
||||
);
|
||||
sendEvent(
|
||||
"keyboardDidShow",
|
||||
createKeyboardEventPayload(
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom),
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.left),
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
|
||||
PixelUtil.toDIPFromPixel(mKeyboardHeight)));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isKeyboardHidden =
|
||||
mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected;
|
||||
boolean isKeyboardHidden = mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected;
|
||||
if (isKeyboardHidden) {
|
||||
mKeyboardHeight = 0;
|
||||
sendEvent("keyboardDidHide",
|
||||
createKeyboardEventPayload(
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.height()),
|
||||
0,
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
|
||||
0
|
||||
)
|
||||
);
|
||||
sendEvent(
|
||||
"keyboardDidHide",
|
||||
createKeyboardEventPayload(
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.height()),
|
||||
0,
|
||||
PixelUtil.toDIPFromPixel(mVisibleViewArea.width()),
|
||||
0));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForDeviceOrientationChanges() {
|
||||
final int rotation =
|
||||
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
|
||||
.getDefaultDisplay().getRotation();
|
||||
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE))
|
||||
.getDefaultDisplay()
|
||||
.getRotation();
|
||||
if (mDeviceRotation == rotation) {
|
||||
return;
|
||||
}
|
||||
@@ -699,9 +699,10 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
private void checkForDeviceDimensionsChanges() {
|
||||
// Get current display metrics.
|
||||
DisplayMetricsHolder.initDisplayMetrics(getContext());
|
||||
// Check changes to both window and screen display metrics since they may not update at the same time.
|
||||
if (!areMetricsEqual(mWindowMetrics, DisplayMetricsHolder.getWindowDisplayMetrics()) ||
|
||||
!areMetricsEqual(mScreenMetrics, DisplayMetricsHolder.getScreenDisplayMetrics())) {
|
||||
// Check changes to both window and screen display metrics since they may not update at the
|
||||
// same time.
|
||||
if (!areMetricsEqual(mWindowMetrics, DisplayMetricsHolder.getWindowDisplayMetrics())
|
||||
|| !areMetricsEqual(mScreenMetrics, DisplayMetricsHolder.getScreenDisplayMetrics())) {
|
||||
mWindowMetrics.setTo(DisplayMetricsHolder.getWindowDisplayMetrics());
|
||||
mScreenMetrics.setTo(DisplayMetricsHolder.getScreenDisplayMetrics());
|
||||
emitUpdateDimensionsEvent();
|
||||
@@ -714,13 +715,13 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
} else {
|
||||
// DisplayMetrics didn't have an equals method before API 17.
|
||||
// Check all public fields manually.
|
||||
return displayMetrics.widthPixels == otherMetrics.widthPixels &&
|
||||
displayMetrics.heightPixels == otherMetrics.heightPixels &&
|
||||
displayMetrics.density == otherMetrics.density &&
|
||||
displayMetrics.densityDpi == otherMetrics.densityDpi &&
|
||||
displayMetrics.scaledDensity == otherMetrics.scaledDensity &&
|
||||
displayMetrics.xdpi == otherMetrics.xdpi &&
|
||||
displayMetrics.ydpi == otherMetrics.ydpi;
|
||||
return displayMetrics.widthPixels == otherMetrics.widthPixels
|
||||
&& displayMetrics.heightPixels == otherMetrics.heightPixels
|
||||
&& displayMetrics.density == otherMetrics.density
|
||||
&& displayMetrics.densityDpi == otherMetrics.densityDpi
|
||||
&& displayMetrics.scaledDensity == otherMetrics.scaledDensity
|
||||
&& displayMetrics.xdpi == otherMetrics.xdpi
|
||||
&& displayMetrics.ydpi == otherMetrics.ydpi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,7 +767,8 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
|
||||
.emitUpdateDimensionsEvent();
|
||||
}
|
||||
|
||||
private WritableMap createKeyboardEventPayload(double screenY, double screenX, double width, double height) {
|
||||
private WritableMap createKeyboardEventPayload(
|
||||
double screenY, double screenX, double width, double height) {
|
||||
WritableMap keyboardEventParams = Arguments.createMap();
|
||||
WritableMap endCoordinates = Arguments.createMap();
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
@@ -17,7 +16,8 @@ public interface ViewManagerOnDemandReactPackage {
|
||||
* Provides a list of names of ViewManagers with which these modules can be accessed from JS.
|
||||
* Typically, this is ViewManager.getName().
|
||||
*/
|
||||
@Nullable List<String> getViewManagerNames(ReactApplicationContext reactContext);
|
||||
@Nullable
|
||||
List<String> getViewManagerNames(ReactApplicationContext reactContext);
|
||||
/**
|
||||
* Creates and returns a ViewManager with a specific name {@param viewManagerName}. It's up to an
|
||||
* implementing package how to interpret the name.
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private final int[] mInputNodes;
|
||||
|
||||
public AdditionAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
ReadableArray inputNodes = config.getArray("input");
|
||||
mInputNodes = new int[inputNodes.size()];
|
||||
@@ -39,8 +37,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
if (animatedNode != null && animatedNode instanceof ValueAnimatedNode) {
|
||||
mValue += ((ValueAnimatedNode) animatedNode).getValue();
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.Add node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.Add node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for all Animated.js library node types that can be created on the "native" side.
|
||||
*/
|
||||
/** Base class for all Animated.js library node types that can be created on the "native" side. */
|
||||
/*package*/ abstract class AnimatedNode {
|
||||
|
||||
public static final int INITIAL_BFS_COLOR = 0;
|
||||
@@ -46,24 +41,19 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Subclasses may want to override this method in order to store a reference to the parent of a
|
||||
* given node that can then be used to calculate current node's value in {@link #update}.
|
||||
* In that case it is important to also override {@link #onDetachedFromNode} to clear that
|
||||
* reference once current node gets detached.
|
||||
* given node that can then be used to calculate current node's value in {@link #update}. In that
|
||||
* case it is important to also override {@link #onDetachedFromNode} to clear that reference once
|
||||
* current node gets detached.
|
||||
*/
|
||||
public void onAttachedToNode(AnimatedNode parent) {
|
||||
}
|
||||
public void onAttachedToNode(AnimatedNode parent) {}
|
||||
|
||||
/**
|
||||
* See {@link #onAttachedToNode}
|
||||
*/
|
||||
public void onDetachedFromNode(AnimatedNode parent) {
|
||||
}
|
||||
/** See {@link #onAttachedToNode} */
|
||||
public void onDetachedFromNode(AnimatedNode parent) {}
|
||||
|
||||
/**
|
||||
* This method will be run on each node at most once every repetition of the animation loop. It
|
||||
* will be executed on a node only when all the node's parent has already been updated. Therefore
|
||||
* it can be used to calculate node's value.
|
||||
*/
|
||||
public void update() {
|
||||
}
|
||||
public void update() {}
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
/**
|
||||
* Interface used to listen to {@link ValueAnimatedNode} updates.
|
||||
*/
|
||||
/** Interface used to listen to {@link ValueAnimatedNode} updates. */
|
||||
public interface AnimatedNodeValueListener {
|
||||
void onValueUpdate(double value);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -36,6 +35,6 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
*/
|
||||
public void resetConfig(ReadableMap config) {
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Animation config for " + getClass().getSimpleName() + " cannot be reset");
|
||||
"Animation config for " + getClass().getSimpleName() + " cannot be reset");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
@@ -54,9 +53,10 @@ public class DecayAnimation extends AnimationDriver {
|
||||
mLastValue = mAnimatedValue.mValue;
|
||||
}
|
||||
|
||||
final double value = mFromValue +
|
||||
(mVelocity / (1 - mDeceleration)) *
|
||||
(1 - Math.exp(-(1 - mDeceleration) * (frameTimeMillis - mStartFrameTimeMillis)));
|
||||
final double value =
|
||||
mFromValue
|
||||
+ (mVelocity / (1 - mDeceleration))
|
||||
* (1 - Math.exp(-(1 - mDeceleration) * (frameTimeMillis - mStartFrameTimeMillis)));
|
||||
|
||||
if (Math.abs(mLastValue - value) < 0.1) {
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
@@ -19,8 +18,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private double mLastValue;
|
||||
|
||||
public DiffClampAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
mInputNodeTag = config.getInt("input");
|
||||
mMin = config.getDouble("min");
|
||||
@@ -41,9 +39,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private double getInputNodeValue() {
|
||||
AnimatedNode animatedNode = mNativeAnimatedNodesManager.getNodeById(mInputNodeTag);
|
||||
if (animatedNode == null || !(animatedNode instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.DiffClamp node");
|
||||
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.DiffClamp node");
|
||||
}
|
||||
|
||||
return ((ValueAnimatedNode) animatedNode).getValue();
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
@@ -12,8 +11,8 @@ import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/**
|
||||
* Animated node which takes two or more value node as an input and outputs an in-order
|
||||
* division of their values.
|
||||
* Animated node which takes two or more value node as an input and outputs an in-order division of
|
||||
* their values.
|
||||
*/
|
||||
/*package*/ class DivisionAnimatedNode extends ValueAnimatedNode {
|
||||
|
||||
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private final int[] mInputNodes;
|
||||
|
||||
public DivisionAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
ReadableArray inputNodes = config.getArray("input");
|
||||
mInputNodes = new int[inputNodes.size()];
|
||||
@@ -42,13 +40,13 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
continue;
|
||||
}
|
||||
if (value == 0) {
|
||||
throw new JSApplicationCausedNativeException("Detected a division by zero in " +
|
||||
"Animated.divide node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Detected a division by zero in " + "Animated.divide node");
|
||||
}
|
||||
mValue /= value;
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.divide node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.divide node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Handles updating a {@link ValueAnimatedNode} when an event gets dispatched.
|
||||
*/
|
||||
/** Handles updating a {@link ValueAnimatedNode} when an event gets dispatched. */
|
||||
/* package */ class EventAnimationDriver implements RCTEventEmitter {
|
||||
private List<String> mEventPath;
|
||||
/* package */ ValueAnimatedNode mValueNode;
|
||||
@@ -44,7 +39,8 @@ import javax.annotation.Nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveTouches(String eventName, WritableArray touches, WritableArray changedIndices) {
|
||||
public void receiveTouches(
|
||||
String eventName, WritableArray touches, WritableArray changedIndices) {
|
||||
throw new RuntimeException("receiveTouches is not support by native animated events");
|
||||
}
|
||||
}
|
||||
|
||||
+6
-7
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
@@ -42,14 +41,14 @@ class FrameBasedAnimationDriver extends AnimationDriver {
|
||||
for (int i = 0; i < numberOfFrames; i++) {
|
||||
mFrames[i] = frames.getDouble(i);
|
||||
}
|
||||
if(config.hasKey("toValue")) {
|
||||
if (config.hasKey("toValue")) {
|
||||
mToValue = config.getType("toValue") == ReadableType.Number ? config.getDouble("toValue") : 0;
|
||||
} else {
|
||||
mToValue = 0;
|
||||
}
|
||||
if(config.hasKey("iterations")) {
|
||||
mIterations = config.getType("iterations") == ReadableType.Number ?
|
||||
config.getInt("iterations") : 1;
|
||||
if (config.hasKey("iterations")) {
|
||||
mIterations =
|
||||
config.getType("iterations") == ReadableType.Number ? config.getInt("iterations") : 1;
|
||||
} else {
|
||||
mIterations = 1;
|
||||
}
|
||||
|
||||
+22
-23
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
@@ -10,17 +10,15 @@ import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Animated node that corresponds to {@code AnimatedInterpolation} from AnimatedImplementation.js.
|
||||
*
|
||||
* Currently only a linear interpolation is supported on an input range of an arbitrary size.
|
||||
* <p>Currently only a linear interpolation is supported on an input range of an arbitrary size.
|
||||
*/
|
||||
/*package*/ class InterpolationAnimatedNode extends ValueAnimatedNode {
|
||||
|
||||
@@ -61,7 +59,7 @@ import javax.annotation.Nullable;
|
||||
break;
|
||||
default:
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Invalid extrapolation type " + extrapolateLeft + "for left extrapolation");
|
||||
"Invalid extrapolation type " + extrapolateLeft + "for left extrapolation");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +74,7 @@ import javax.annotation.Nullable;
|
||||
break;
|
||||
default:
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Invalid extrapolation type " + extrapolateRight + "for right extrapolation");
|
||||
"Invalid extrapolation type " + extrapolateRight + "for right extrapolation");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +89,7 @@ import javax.annotation.Nullable;
|
||||
return outputMax;
|
||||
}
|
||||
|
||||
return outputMin + (outputMax - outputMin) *
|
||||
(result - inputMin) / (inputMax - inputMin);
|
||||
return outputMin + (outputMax - outputMin) * (result - inputMin) / (inputMax - inputMin);
|
||||
}
|
||||
|
||||
/*package*/ static double interpolate(
|
||||
@@ -100,17 +97,16 @@ import javax.annotation.Nullable;
|
||||
double[] inputRange,
|
||||
double[] outputRange,
|
||||
String extrapolateLeft,
|
||||
String extrapolateRight
|
||||
) {
|
||||
String extrapolateRight) {
|
||||
int rangeIndex = findRangeIndex(value, inputRange);
|
||||
return interpolate(
|
||||
value,
|
||||
inputRange[rangeIndex],
|
||||
inputRange[rangeIndex + 1],
|
||||
outputRange[rangeIndex],
|
||||
outputRange[rangeIndex + 1],
|
||||
extrapolateLeft,
|
||||
extrapolateRight);
|
||||
value,
|
||||
inputRange[rangeIndex],
|
||||
inputRange[rangeIndex + 1],
|
||||
outputRange[rangeIndex],
|
||||
outputRange[rangeIndex + 1],
|
||||
extrapolateLeft,
|
||||
extrapolateRight);
|
||||
}
|
||||
|
||||
private static int findRangeIndex(double value, double[] ranges) {
|
||||
@@ -228,16 +224,19 @@ import javax.annotation.Nullable;
|
||||
int i = 0;
|
||||
mSOutputMatcher.reset();
|
||||
while (mSOutputMatcher.find()) {
|
||||
double val = interpolate(value, mInputRange, mOutputs[i++], mExtrapolateLeft, mExtrapolateRight);
|
||||
double val =
|
||||
interpolate(value, mInputRange, mOutputs[i++], mExtrapolateLeft, mExtrapolateRight);
|
||||
if (mShouldRound) {
|
||||
// rgba requires that the r,g,b are integers.... so we want to round them, but we *dont* want to
|
||||
// rgba requires that the r,g,b are integers.... so we want to round them, but we *dont*
|
||||
// want to
|
||||
// round the opacity (4th column).
|
||||
boolean isAlpha = i == 4;
|
||||
int rounded = (int)Math.round(isAlpha ? val * 1000 : val);
|
||||
String num = isAlpha ? Double.toString((double)rounded / 1000) : Integer.toString(rounded);
|
||||
int rounded = (int) Math.round(isAlpha ? val * 1000 : val);
|
||||
String num =
|
||||
isAlpha ? Double.toString((double) rounded / 1000) : Integer.toString(rounded);
|
||||
mSOutputMatcher.appendReplacement(sb, num);
|
||||
} else {
|
||||
int intVal = (int)val;
|
||||
int intVal = (int) val;
|
||||
String num = intVal != val ? Double.toString(val) : Integer.toString(intVal);
|
||||
mSOutputMatcher.appendReplacement(sb, num);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/*package*/ class ModulusAnimatedNode extends ValueAnimatedNode {
|
||||
@@ -18,8 +16,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private final double mModulus;
|
||||
|
||||
public ModulusAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
mInputNode = config.getInt("input");
|
||||
mModulus = config.getDouble("modulus");
|
||||
@@ -32,8 +29,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
final double value = ((ValueAnimatedNode) animatedNode).getValue();
|
||||
mValue = (value % mModulus + mModulus) % mModulus;
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.modulus node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.modulus node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private final int[] mInputNodes;
|
||||
|
||||
public MultiplicationAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
ReadableArray inputNodes = config.getArray("input");
|
||||
mInputNodes = new int[inputNodes.size()];
|
||||
@@ -39,8 +37,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
if (animatedNode != null && animatedNode instanceof ValueAnimatedNode) {
|
||||
mValue *= ((ValueAnimatedNode) animatedNode).getValue();
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.multiply node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.multiply node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+214
-196
@@ -1,16 +1,11 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -29,51 +24,51 @@ import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||
import com.facebook.react.uimanager.UIBlock;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.UIManagerModuleListener;
|
||||
import java.util.ArrayList;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Module that exposes interface for creating and managing animated nodes on the "native" side.
|
||||
*
|
||||
* Animated.js library is based on a concept of a graph where nodes are values or transform
|
||||
* <p>Animated.js library is based on a concept of a graph where nodes are values or transform
|
||||
* operations (such as interpolation, addition, etc) and connection are used to describe how change
|
||||
* of the value in one node can affect other nodes.
|
||||
*
|
||||
* Few examples of the nodes that can be created on the JS side:
|
||||
* - Animated.Value is a simplest type of node with a numeric value which can be driven by an
|
||||
* animation engine (spring, decay, etc) or by calling setValue on it directly from JS
|
||||
* - Animated.add is a type of node that may have two or more input nodes. It outputs the sum of
|
||||
* all the input node values
|
||||
* - interpolate - is actually a method you can call on any node and it creates a new node that
|
||||
* takes the parent node as an input and outputs its interpolated value (e.g. if you have value
|
||||
* that can animate from 0 to 1 you can create interpolated node and set output range to be 0 to
|
||||
* 100 and when the input node changes the output of interpolated node will multiply the values
|
||||
* by 100)
|
||||
* <p>Few examples of the nodes that can be created on the JS side: - Animated.Value is a simplest
|
||||
* type of node with a numeric value which can be driven by an animation engine (spring, decay, etc)
|
||||
* or by calling setValue on it directly from JS - Animated.add is a type of node that may have two
|
||||
* or more input nodes. It outputs the sum of all the input node values - interpolate - is actually
|
||||
* a method you can call on any node and it creates a new node that takes the parent node as an
|
||||
* input and outputs its interpolated value (e.g. if you have value that can animate from 0 to 1 you
|
||||
* can create interpolated node and set output range to be 0 to 100 and when the input node changes
|
||||
* the output of interpolated node will multiply the values by 100)
|
||||
*
|
||||
* You can mix and chain nodes however you like and this way create nodes graph with connections
|
||||
* <p>You can mix and chain nodes however you like and this way create nodes graph with connections
|
||||
* between them.
|
||||
*
|
||||
* To map animated node values to view properties there is a special type of a node: AnimatedProps.
|
||||
* It is created by AnimatedImplementation whenever you render Animated.View and stores a mapping
|
||||
* from the view properties to the corresponding animated values (so it's actually also a node with
|
||||
* connections to the value nodes).
|
||||
* <p>To map animated node values to view properties there is a special type of a node:
|
||||
* AnimatedProps. It is created by AnimatedImplementation whenever you render Animated.View and
|
||||
* stores a mapping from the view properties to the corresponding animated values (so it's actually
|
||||
* also a node with connections to the value nodes).
|
||||
*
|
||||
* Last "special" elements of the the graph are "animation drivers". Those are objects (represented
|
||||
* as a graph nodes too) that based on some criteria updates attached values every frame (we have
|
||||
* few types of those, e.g., spring, timing, decay). Animation objects can be "started" and
|
||||
* "stopped". Those are like "pulse generators" for the rest of the nodes graph. Those pulses then
|
||||
* propagate along the graph to the children nodes up to the special node type: AnimatedProps which
|
||||
* then can be used to calculate property update map for a view.
|
||||
* <p>Last "special" elements of the the graph are "animation drivers". Those are objects
|
||||
* (represented as a graph nodes too) that based on some criteria updates attached values every
|
||||
* frame (we have few types of those, e.g., spring, timing, decay). Animation objects can be
|
||||
* "started" and "stopped". Those are like "pulse generators" for the rest of the nodes graph. Those
|
||||
* pulses then propagate along the graph to the children nodes up to the special node type:
|
||||
* AnimatedProps which then can be used to calculate property update map for a view.
|
||||
*
|
||||
* This class acts as a proxy between the "native" API that can be called from JS and the main class
|
||||
* that coordinates all the action: {@link NativeAnimatedNodesManager}. Since all the methods from
|
||||
* {@link NativeAnimatedNodesManager} need to be called from the UI thread, we we create a queue of
|
||||
* animated graph operations that is then enqueued to be executed in the UI Thread at the end of the
|
||||
* batch of JS->native calls (similarly to how it's handled in {@link UIManagerModule}). This
|
||||
* isolates us from the problems that may be caused by concurrent updates of animated graph while UI
|
||||
* thread is "executing" the animation loop.
|
||||
* <p>This class acts as a proxy between the "native" API that can be called from JS and the main
|
||||
* class that coordinates all the action: {@link NativeAnimatedNodesManager}. Since all the methods
|
||||
* from {@link NativeAnimatedNodesManager} need to be called from the UI thread, we we create a
|
||||
* queue of animated graph operations that is then enqueued to be executed in the UI Thread at the
|
||||
* end of the batch of JS->native calls (similarly to how it's handled in {@link UIManagerModule}).
|
||||
* This isolates us from the problems that may be caused by concurrent updates of animated graph
|
||||
* while UI thread is "executing" the animation loop.
|
||||
*/
|
||||
@ReactModule(name = NativeAnimatedModule.NAME)
|
||||
public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
LifecycleEventListener, UIManagerModuleListener {
|
||||
public class NativeAnimatedModule extends ReactContextBaseJavaModule
|
||||
implements LifecycleEventListener, UIManagerModuleListener {
|
||||
|
||||
public static final String NAME = "NativeAnimatedModule";
|
||||
|
||||
@@ -92,23 +87,25 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
super(reactContext);
|
||||
|
||||
mReactChoreographer = ReactChoreographer.getInstance();
|
||||
mAnimatedFrameCallback = new GuardedFrameCallback(reactContext) {
|
||||
@Override
|
||||
protected void doFrameGuarded(final long frameTimeNanos) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
if (nodesManager.hasActiveAnimations()) {
|
||||
nodesManager.runUpdates(frameTimeNanos);
|
||||
}
|
||||
mAnimatedFrameCallback =
|
||||
new GuardedFrameCallback(reactContext) {
|
||||
@Override
|
||||
protected void doFrameGuarded(final long frameTimeNanos) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
if (nodesManager.hasActiveAnimations()) {
|
||||
nodesManager.runUpdates(frameTimeNanos);
|
||||
}
|
||||
|
||||
// TODO: Would be great to avoid adding this callback in case there are no active animations
|
||||
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
|
||||
// be posted from the UI thread and therefore we cannot schedule them directly from
|
||||
// @ReactMethod methods
|
||||
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
|
||||
mAnimatedFrameCallback);
|
||||
}
|
||||
};
|
||||
// TODO: Would be great to avoid adding this callback in case there are no active
|
||||
// animations
|
||||
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
|
||||
// be posted from the UI thread and therefore we cannot schedule them directly from
|
||||
// @ReactMethod methods
|
||||
Assertions.assertNotNull(mReactChoreographer)
|
||||
.postFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,24 +130,26 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
final ArrayList<UIThreadOperation> operations = mOperations;
|
||||
mPreOperations = new ArrayList<>();
|
||||
mOperations = new ArrayList<>();
|
||||
uiManager.prependUIBlock(new UIBlock() {
|
||||
@Override
|
||||
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
for (UIThreadOperation operation : preOperations) {
|
||||
operation.execute(nodesManager);
|
||||
}
|
||||
}
|
||||
});
|
||||
uiManager.addUIBlock(new UIBlock() {
|
||||
@Override
|
||||
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
for (UIThreadOperation operation : operations) {
|
||||
operation.execute(nodesManager);
|
||||
}
|
||||
}
|
||||
});
|
||||
uiManager.prependUIBlock(
|
||||
new UIBlock() {
|
||||
@Override
|
||||
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
for (UIThreadOperation operation : preOperations) {
|
||||
operation.execute(nodesManager);
|
||||
}
|
||||
}
|
||||
});
|
||||
uiManager.addUIBlock(
|
||||
new UIBlock() {
|
||||
@Override
|
||||
public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
|
||||
NativeAnimatedNodesManager nodesManager = getNodesManager();
|
||||
for (UIThreadOperation operation : operations) {
|
||||
operation.execute(nodesManager);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,7 +169,8 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
|
||||
private NativeAnimatedNodesManager getNodesManager() {
|
||||
if (mNodesManager == null) {
|
||||
UIManagerModule uiManager = getReactApplicationContext().getNativeModule(UIManagerModule.class);
|
||||
UIManagerModule uiManager =
|
||||
getReactApplicationContext().getNativeModule(UIManagerModule.class);
|
||||
mNodesManager = new NativeAnimatedNodesManager(uiManager);
|
||||
}
|
||||
|
||||
@@ -178,15 +178,15 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
}
|
||||
|
||||
private void clearFrameCallback() {
|
||||
Assertions.assertNotNull(mReactChoreographer).removeFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
|
||||
mAnimatedFrameCallback);
|
||||
Assertions.assertNotNull(mReactChoreographer)
|
||||
.removeFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
|
||||
}
|
||||
|
||||
private void enqueueFrameCallback() {
|
||||
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
|
||||
mAnimatedFrameCallback);
|
||||
Assertions.assertNotNull(mReactChoreographer)
|
||||
.postFrameCallback(
|
||||
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE, mAnimatedFrameCallback);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -196,92 +196,102 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
|
||||
@ReactMethod
|
||||
public void createAnimatedNode(final int tag, final ReadableMap config) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.createAnimatedNode(tag, config);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.createAnimatedNode(tag, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void startListeningToAnimatedNodeValue(final int tag) {
|
||||
final AnimatedNodeValueListener listener = new AnimatedNodeValueListener() {
|
||||
public void onValueUpdate(double value) {
|
||||
WritableMap onAnimatedValueData = Arguments.createMap();
|
||||
onAnimatedValueData.putInt("tag", tag);
|
||||
onAnimatedValueData.putDouble("value", value);
|
||||
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit("onAnimatedValueUpdate", onAnimatedValueData);
|
||||
}
|
||||
};
|
||||
final AnimatedNodeValueListener listener =
|
||||
new AnimatedNodeValueListener() {
|
||||
public void onValueUpdate(double value) {
|
||||
WritableMap onAnimatedValueData = Arguments.createMap();
|
||||
onAnimatedValueData.putInt("tag", tag);
|
||||
onAnimatedValueData.putDouble("value", value);
|
||||
getReactApplicationContext()
|
||||
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
|
||||
.emit("onAnimatedValueUpdate", onAnimatedValueData);
|
||||
}
|
||||
};
|
||||
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.startListeningToAnimatedNodeValue(tag, listener);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.startListeningToAnimatedNodeValue(tag, listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void stopListeningToAnimatedNodeValue(final int tag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.stopListeningToAnimatedNodeValue(tag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.stopListeningToAnimatedNodeValue(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void dropAnimatedNode(final int tag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.dropAnimatedNode(tag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.dropAnimatedNode(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setAnimatedNodeValue(final int tag, final double value) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.setAnimatedNodeValue(tag, value);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.setAnimatedNodeValue(tag, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setAnimatedNodeOffset(final int tag, final double value) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.setAnimatedNodeOffset(tag, value);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.setAnimatedNodeOffset(tag, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void flattenAnimatedNodeOffset(final int tag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.flattenAnimatedNodeOffset(tag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.flattenAnimatedNodeOffset(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void extractAnimatedNodeOffset(final int tag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.extractAnimatedNodeOffset(tag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.extractAnimatedNodeOffset(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
@@ -290,91 +300,99 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
|
||||
final int animatedNodeTag,
|
||||
final ReadableMap animationConfig,
|
||||
final Callback endCallback) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.startAnimatingNode(
|
||||
animationId,
|
||||
animatedNodeTag,
|
||||
animationConfig,
|
||||
endCallback);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.startAnimatingNode(
|
||||
animationId, animatedNodeTag, animationConfig, endCallback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void stopAnimation(final int animationId) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.stopAnimation(animationId);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.stopAnimation(animationId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void connectAnimatedNodes(final int parentNodeTag, final int childNodeTag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.connectAnimatedNodes(parentNodeTag, childNodeTag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.connectAnimatedNodes(parentNodeTag, childNodeTag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void disconnectAnimatedNodes(final int parentNodeTag, final int childNodeTag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.disconnectAnimatedNodes(parentNodeTag, childNodeTag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.disconnectAnimatedNodes(parentNodeTag, childNodeTag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void connectAnimatedNodeToView(final int animatedNodeTag, final int viewTag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.connectAnimatedNodeToView(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.connectAnimatedNodeToView(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void disconnectAnimatedNodeFromView(final int animatedNodeTag, final int viewTag) {
|
||||
mPreOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.restoreDefaultValues(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.disconnectAnimatedNodeFromView(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
mPreOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.restoreDefaultValues(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.disconnectAnimatedNodeFromView(animatedNodeTag, viewTag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void addAnimatedEventToView(final int viewTag, final String eventName, final ReadableMap eventMapping) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.addAnimatedEventToView(viewTag, eventName, eventMapping);
|
||||
}
|
||||
});
|
||||
public void addAnimatedEventToView(
|
||||
final int viewTag, final String eventName, final ReadableMap eventMapping) {
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.addAnimatedEventToView(viewTag, eventName, eventMapping);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void removeAnimatedEventFromView(final int viewTag, final String eventName, final int animatedValueTag) {
|
||||
mOperations.add(new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.removeAnimatedEventFromView(viewTag, eventName, animatedValueTag);
|
||||
}
|
||||
});
|
||||
public void removeAnimatedEventFromView(
|
||||
final int viewTag, final String eventName, final int animatedValueTag) {
|
||||
mOperations.add(
|
||||
new UIThreadOperation() {
|
||||
@Override
|
||||
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
|
||||
animatedNodesManager.removeAnimatedEventFromView(viewTag, eventName, animatedValueTag);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+87
-75
@@ -1,14 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
@@ -22,7 +20,6 @@ import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.EventDispatcherListener;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -31,21 +28,20 @@ import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is the main class that coordinates how native animated JS implementation drives UI changes.
|
||||
*
|
||||
* It implements a management interface for animated nodes graph as well as implements a graph
|
||||
* <p>It implements a management interface for animated nodes graph as well as implements a graph
|
||||
* traversal algorithm that is run for each animation frame.
|
||||
*
|
||||
* For each animation frame we visit animated nodes that might've been updated as well as their
|
||||
* <p>For each animation frame we visit animated nodes that might've been updated as well as their
|
||||
* children that may use parent's values to update themselves. At the end of the traversal algorithm
|
||||
* we expect to reach a special type of the node: PropsAnimatedNode that is then responsible for
|
||||
* calculating property map which can be sent to native view hierarchy to update the view.
|
||||
*
|
||||
* IMPORTANT: This class should be accessed only from the UI Thread
|
||||
* <p>IMPORTANT: This class should be accessed only from the UI Thread
|
||||
*/
|
||||
/*package*/ class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
|
||||
@@ -67,7 +63,8 @@ import javax.annotation.Nullable;
|
||||
mCustomEventNamesResolver = uiManager.getDirectEventNamesResolver();
|
||||
}
|
||||
|
||||
/*package*/ @Nullable AnimatedNode getNodeById(int id) {
|
||||
/*package*/ @Nullable
|
||||
AnimatedNode getNodeById(int id) {
|
||||
return mAnimatedNodes.get(id);
|
||||
}
|
||||
|
||||
@@ -77,8 +74,8 @@ import javax.annotation.Nullable;
|
||||
|
||||
public void createAnimatedNode(int tag, ReadableMap config) {
|
||||
if (mAnimatedNodes.get(tag) != null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" already exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " already exists");
|
||||
}
|
||||
String type = config.getString("type");
|
||||
final AnimatedNode node;
|
||||
@@ -122,8 +119,8 @@ import javax.annotation.Nullable;
|
||||
public void startListeningToAnimatedNodeValue(int tag, AnimatedNodeValueListener listener) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
((ValueAnimatedNode) node).setValueListener(listener);
|
||||
}
|
||||
@@ -131,8 +128,8 @@ import javax.annotation.Nullable;
|
||||
public void stopListeningToAnimatedNodeValue(int tag) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
((ValueAnimatedNode) node).setValueListener(null);
|
||||
}
|
||||
@@ -140,8 +137,8 @@ import javax.annotation.Nullable;
|
||||
public void setAnimatedNodeValue(int tag, double value) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
stopAnimationsForNode(node);
|
||||
((ValueAnimatedNode) node).mValue = value;
|
||||
@@ -151,8 +148,8 @@ import javax.annotation.Nullable;
|
||||
public void setAnimatedNodeOffset(int tag, double offset) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
((ValueAnimatedNode) node).mOffset = offset;
|
||||
mUpdatedNodes.put(tag, node);
|
||||
@@ -161,8 +158,8 @@ import javax.annotation.Nullable;
|
||||
public void flattenAnimatedNodeOffset(int tag) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
((ValueAnimatedNode) node).flattenOffset();
|
||||
}
|
||||
@@ -170,25 +167,22 @@ import javax.annotation.Nullable;
|
||||
public void extractAnimatedNodeOffset(int tag) {
|
||||
AnimatedNode node = mAnimatedNodes.get(tag);
|
||||
if (node == null || !(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag +
|
||||
" does not exists or is not a 'value' node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
|
||||
}
|
||||
((ValueAnimatedNode) node).extractOffset();
|
||||
}
|
||||
|
||||
public void startAnimatingNode(
|
||||
int animationId,
|
||||
int animatedNodeTag,
|
||||
ReadableMap animationConfig,
|
||||
Callback endCallback) {
|
||||
int animationId, int animatedNodeTag, ReadableMap animationConfig, Callback endCallback) {
|
||||
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
|
||||
if (node == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + animatedNodeTag + " does not exists");
|
||||
}
|
||||
if (!(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node should be of type " +
|
||||
ValueAnimatedNode.class.getName());
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node should be of type " + ValueAnimatedNode.class.getName());
|
||||
}
|
||||
|
||||
final AnimationDriver existingDriver = mActiveAnimations.get(animationId);
|
||||
@@ -263,13 +257,13 @@ import javax.annotation.Nullable;
|
||||
public void connectAnimatedNodes(int parentNodeTag, int childNodeTag) {
|
||||
AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag);
|
||||
if (parentNode == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + parentNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + parentNodeTag + " does not exists");
|
||||
}
|
||||
AnimatedNode childNode = mAnimatedNodes.get(childNodeTag);
|
||||
if (childNode == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + childNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + childNodeTag + " does not exists");
|
||||
}
|
||||
parentNode.addChild(childNode);
|
||||
mUpdatedNodes.put(childNodeTag, childNode);
|
||||
@@ -278,13 +272,13 @@ import javax.annotation.Nullable;
|
||||
public void disconnectAnimatedNodes(int parentNodeTag, int childNodeTag) {
|
||||
AnimatedNode parentNode = mAnimatedNodes.get(parentNodeTag);
|
||||
if (parentNode == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + parentNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + parentNodeTag + " does not exists");
|
||||
}
|
||||
AnimatedNode childNode = mAnimatedNodes.get(childNodeTag);
|
||||
if (childNode == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + childNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + childNodeTag + " does not exists");
|
||||
}
|
||||
parentNode.removeChild(childNode);
|
||||
mUpdatedNodes.put(childNodeTag, childNode);
|
||||
@@ -293,12 +287,14 @@ import javax.annotation.Nullable;
|
||||
public void connectAnimatedNodeToView(int animatedNodeTag, int viewTag) {
|
||||
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
|
||||
if (node == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + animatedNodeTag + " does not exists");
|
||||
}
|
||||
if (!(node instanceof PropsAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
|
||||
"of type " + PropsAnimatedNode.class.getName());
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node connected to view should be"
|
||||
+ "of type "
|
||||
+ PropsAnimatedNode.class.getName());
|
||||
}
|
||||
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
|
||||
propsAnimatedNode.connectToView(viewTag);
|
||||
@@ -308,12 +304,14 @@ import javax.annotation.Nullable;
|
||||
public void disconnectAnimatedNodeFromView(int animatedNodeTag, int viewTag) {
|
||||
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
|
||||
if (node == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + animatedNodeTag + " does not exists");
|
||||
}
|
||||
if (!(node instanceof PropsAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
|
||||
"of type " + PropsAnimatedNode.class.getName());
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node connected to view should be"
|
||||
+ "of type "
|
||||
+ PropsAnimatedNode.class.getName());
|
||||
}
|
||||
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
|
||||
propsAnimatedNode.disconnectFromView(viewTag);
|
||||
@@ -329,8 +327,10 @@ import javax.annotation.Nullable;
|
||||
return;
|
||||
}
|
||||
if (!(node instanceof PropsAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" +
|
||||
"of type " + PropsAnimatedNode.class.getName());
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node connected to view should be"
|
||||
+ "of type "
|
||||
+ PropsAnimatedNode.class.getName());
|
||||
}
|
||||
PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node;
|
||||
propsAnimatedNode.restoreDefaultValues();
|
||||
@@ -340,12 +340,14 @@ import javax.annotation.Nullable;
|
||||
int nodeTag = eventMapping.getInt("animatedValueTag");
|
||||
AnimatedNode node = mAnimatedNodes.get(nodeTag);
|
||||
if (node == null) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node with tag " + nodeTag +
|
||||
" does not exists");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node with tag " + nodeTag + " does not exists");
|
||||
}
|
||||
if (!(node instanceof ValueAnimatedNode)) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node connected to event should be" +
|
||||
"of type " + ValueAnimatedNode.class.getName());
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node connected to event should be"
|
||||
+ "of type "
|
||||
+ ValueAnimatedNode.class.getName());
|
||||
}
|
||||
|
||||
ReadableArray path = eventMapping.getArray("nativeEventPath");
|
||||
@@ -390,12 +392,13 @@ import javax.annotation.Nullable;
|
||||
if (UiThreadUtil.isOnUiThread()) {
|
||||
handleEvent(event);
|
||||
} else {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
UiThreadUtil.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
handleEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,12 +420,12 @@ import javax.annotation.Nullable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animation loop performs two BFSes over the graph of animated nodes. We use incremented
|
||||
* {@code mAnimatedGraphBFSColor} to mark nodes as visited in each of the BFSes which saves
|
||||
* additional loops for clearing "visited" states.
|
||||
* Animation loop performs two BFSes over the graph of animated nodes. We use incremented {@code
|
||||
* mAnimatedGraphBFSColor} to mark nodes as visited in each of the BFSes which saves additional
|
||||
* loops for clearing "visited" states.
|
||||
*
|
||||
* First BFS starts with nodes that are in {@code mUpdatedNodes} (that is, their value have been
|
||||
* modified from JS in the last batch of JS operations) or directly attached to an active
|
||||
* <p>First BFS starts with nodes that are in {@code mUpdatedNodes} (that is, their value have
|
||||
* been modified from JS in the last batch of JS operations) or directly attached to an active
|
||||
* animation (hence linked to objects from {@code mActiveAnimations}). In that step we calculate
|
||||
* an attribute {@code mActiveIncomingNodes}. The second BFS runs in topological order over the
|
||||
* sub-graph of *active* nodes. This is done by adding node to the BFS queue only if all its
|
||||
@@ -543,14 +546,20 @@ import javax.annotation.Nullable;
|
||||
try {
|
||||
((PropsAnimatedNode) nextNode).updateView();
|
||||
} catch (IllegalViewOperationException e) {
|
||||
// An exception is thrown if the view hasn't been created yet. This can happen because views are
|
||||
// created in batches. If this particular view didn't make it into a batch yet, the view won't
|
||||
// exist and an exception will be thrown when attempting to start an animation on it.
|
||||
//
|
||||
// Eat the exception rather than crashing. The impact is that we may drop one or more frames of the
|
||||
// animation.
|
||||
FLog.e(ReactConstants.TAG, "Native animation workaround, frame lost as result of race condition", e);
|
||||
}
|
||||
// An exception is thrown if the view hasn't been created yet. This can happen because
|
||||
// views are
|
||||
// created in batches. If this particular view didn't make it into a batch yet, the view
|
||||
// won't
|
||||
// exist and an exception will be thrown when attempting to start an animation on it.
|
||||
//
|
||||
// Eat the exception rather than crashing. The impact is that we may drop one or more
|
||||
// frames of the
|
||||
// animation.
|
||||
FLog.e(
|
||||
ReactConstants.TAG,
|
||||
"Native animation workaround, frame lost as result of race condition",
|
||||
e);
|
||||
}
|
||||
}
|
||||
if (nextNode instanceof ValueAnimatedNode) {
|
||||
// Potentially send events to JS when the node's value is updated
|
||||
@@ -574,8 +583,11 @@ import javax.annotation.Nullable;
|
||||
// visited in the step above so that all the nodes properties `mActiveIncomingNodes` are set to
|
||||
// zero
|
||||
if (activeNodesCount != updatedNodesCount) {
|
||||
throw new IllegalStateException("Looks like animated nodes graph has cycles, there are "
|
||||
+ activeNodesCount + " but toposort visited only " + updatedNodesCount);
|
||||
throw new IllegalStateException(
|
||||
"Looks like animated nodes graph has cycles, there are "
|
||||
+ activeNodesCount
|
||||
+ " but toposort visited only "
|
||||
+ updatedNodesCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,24 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
|
||||
import com.facebook.react.bridge.UIManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Animated node that represents view properties. There is a special handling logic implemented for
|
||||
* the nodes of this type in {@link NativeAnimatedNodesManager} that is responsible for extracting
|
||||
* a map of updated properties, which can be then passed down to the view.
|
||||
* the nodes of this type in {@link NativeAnimatedNodesManager} that is responsible for extracting a
|
||||
* map of updated properties, which can be then passed down to the view.
|
||||
*/
|
||||
/*package*/ class PropsAnimatedNode extends AnimatedNode {
|
||||
|
||||
@@ -31,7 +28,10 @@ import javax.annotation.Nullable;
|
||||
private final Map<String, Integer> mPropNodeMapping;
|
||||
private final JavaOnlyMap mPropMap;
|
||||
|
||||
PropsAnimatedNode(ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager, UIManager uiManager) {
|
||||
PropsAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager,
|
||||
UIManager uiManager) {
|
||||
ReadableMap props = config.getMap("props");
|
||||
ReadableMapKeySetIterator iter = props.keySetIterator();
|
||||
mPropNodeMapping = new HashMap<>();
|
||||
@@ -47,16 +47,17 @@ import javax.annotation.Nullable;
|
||||
|
||||
public void connectToView(int viewTag) {
|
||||
if (mConnectedViewTag != -1) {
|
||||
throw new JSApplicationIllegalArgumentException("Animated node " + mTag + " is " +
|
||||
"already attached to a view");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node " + mTag + " is " + "already attached to a view");
|
||||
}
|
||||
mConnectedViewTag = viewTag;
|
||||
}
|
||||
|
||||
public void disconnectFromView(int viewTag) {
|
||||
if (mConnectedViewTag != viewTag) {
|
||||
throw new JSApplicationIllegalArgumentException("Attempting to disconnect view that has " +
|
||||
"not been connected with the given animated node");
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Attempting to disconnect view that has "
|
||||
+ "not been connected with the given animated node");
|
||||
}
|
||||
|
||||
mConnectedViewTag = -1;
|
||||
@@ -64,13 +65,11 @@ import javax.annotation.Nullable;
|
||||
|
||||
public void restoreDefaultValues() {
|
||||
ReadableMapKeySetIterator it = mPropMap.keySetIterator();
|
||||
while(it.hasNextKey()) {
|
||||
while (it.hasNextKey()) {
|
||||
mPropMap.putNull(it.nextKey());
|
||||
}
|
||||
|
||||
mUIManager.synchronouslyUpdateViewOnUIThread(
|
||||
mConnectedViewTag,
|
||||
mPropMap);
|
||||
mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap);
|
||||
}
|
||||
|
||||
public final void updateView() {
|
||||
@@ -86,18 +85,16 @@ import javax.annotation.Nullable;
|
||||
} else if (node instanceof ValueAnimatedNode) {
|
||||
Object animatedObject = ((ValueAnimatedNode) node).getAnimatedObject();
|
||||
if (animatedObject instanceof String) {
|
||||
mPropMap.putString(entry.getKey(), (String)animatedObject);
|
||||
mPropMap.putString(entry.getKey(), (String) animatedObject);
|
||||
} else {
|
||||
mPropMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported type of node used in property node " +
|
||||
node.getClass());
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported type of node used in property node " + node.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
mUIManager.synchronouslyUpdateViewOnUIThread(
|
||||
mConnectedViewTag,
|
||||
mPropMap);
|
||||
mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/**
|
||||
* Implementation of {@link AnimationDriver} providing support for spring animations. The
|
||||
* implementation has been copied from android implementation of Rebound library (see
|
||||
* <a href="http://facebook.github.io/rebound/">http://facebook.github.io/rebound/</a>)
|
||||
* implementation has been copied from android implementation of Rebound library (see <a
|
||||
* href="http://facebook.github.io/rebound/">http://facebook.github.io/rebound/</a>)
|
||||
*/
|
||||
/*package*/ class SpringAnimation extends AnimationDriver {
|
||||
|
||||
@@ -101,6 +100,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/**
|
||||
* get the displacement from rest for a given physics state
|
||||
*
|
||||
* @param state the state to measure from
|
||||
* @return the distance displaced by
|
||||
*/
|
||||
@@ -110,22 +110,24 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
/**
|
||||
* check if the current state is at rest
|
||||
*
|
||||
* @return is the spring at rest
|
||||
*/
|
||||
private boolean isAtRest() {
|
||||
return Math.abs(mCurrentState.velocity) <= mRestSpeedThreshold &&
|
||||
(getDisplacementDistanceForState(mCurrentState) <= mDisplacementFromRestThreshold ||
|
||||
mSpringStiffness == 0);
|
||||
return Math.abs(mCurrentState.velocity) <= mRestSpeedThreshold
|
||||
&& (getDisplacementDistanceForState(mCurrentState) <= mDisplacementFromRestThreshold
|
||||
|| mSpringStiffness == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the spring is overshooting beyond its target.
|
||||
*
|
||||
* @return true if the spring is overshooting its target
|
||||
*/
|
||||
private boolean isOvershooting() {
|
||||
return mSpringStiffness > 0 &&
|
||||
((mStartValue < mEndValue && mCurrentState.position > mEndValue) ||
|
||||
(mStartValue > mEndValue && mCurrentState.position < mEndValue));
|
||||
return mSpringStiffness > 0
|
||||
&& ((mStartValue < mEndValue && mCurrentState.position > mEndValue)
|
||||
|| (mStartValue > mEndValue && mCurrentState.position < mEndValue));
|
||||
}
|
||||
|
||||
private void advance(double realDeltaTime) {
|
||||
@@ -147,7 +149,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
double k = mSpringStiffness;
|
||||
double v0 = -mInitialVelocity;
|
||||
|
||||
double zeta = c / (2 * Math.sqrt(k * m ));
|
||||
double zeta = c / (2 * Math.sqrt(k * m));
|
||||
double omega0 = Math.sqrt(k / m);
|
||||
double omega1 = omega0 * Math.sqrt(1.0 - (zeta * zeta));
|
||||
double x0 = mEndValue - mStartValue;
|
||||
@@ -159,27 +161,26 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
// Under damped
|
||||
double envelope = Math.exp(-zeta * omega0 * t);
|
||||
position =
|
||||
mEndValue -
|
||||
envelope *
|
||||
((v0 + zeta * omega0 * x0) / omega1 * Math.sin(omega1 * t) +
|
||||
x0 * Math.cos(omega1 * t));
|
||||
mEndValue
|
||||
- envelope
|
||||
* ((v0 + zeta * omega0 * x0) / omega1 * Math.sin(omega1 * t)
|
||||
+ x0 * Math.cos(omega1 * t));
|
||||
// This looks crazy -- it's actually just the derivative of the
|
||||
// oscillation function
|
||||
velocity =
|
||||
zeta *
|
||||
omega0 *
|
||||
envelope *
|
||||
(Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0) / omega1 +
|
||||
x0 * Math.cos(omega1 * t)) -
|
||||
envelope *
|
||||
(Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0) -
|
||||
omega1 * x0 * Math.sin(omega1 * t));
|
||||
zeta
|
||||
* omega0
|
||||
* envelope
|
||||
* (Math.sin(omega1 * t) * (v0 + zeta * omega0 * x0) / omega1
|
||||
+ x0 * Math.cos(omega1 * t))
|
||||
- envelope
|
||||
* (Math.cos(omega1 * t) * (v0 + zeta * omega0 * x0)
|
||||
- omega1 * x0 * Math.sin(omega1 * t));
|
||||
} else {
|
||||
// Critically damped spring
|
||||
double envelope = Math.exp(-omega0 * t);
|
||||
position = mEndValue - envelope * (x0 + (v0 + omega0 * x0) * t);
|
||||
velocity =
|
||||
envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0));
|
||||
velocity = envelope * (v0 * (t * omega0 - 1) + t * x0 * (omega0 * omega0));
|
||||
}
|
||||
|
||||
mCurrentState.position = position;
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@@ -46,8 +43,8 @@ import javax.annotation.Nullable;
|
||||
} else if (node instanceof ValueAnimatedNode) {
|
||||
propsMap.putDouble(entry.getKey(), ((ValueAnimatedNode) node).getValue());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported type of node used in property node " +
|
||||
node.getClass());
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported type of node used in property node " + node.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationCausedNativeException;
|
||||
@@ -21,8 +20,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
private final int[] mInputNodes;
|
||||
|
||||
public SubtractionAnimatedNode(
|
||||
ReadableMap config,
|
||||
NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
|
||||
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
|
||||
ReadableArray inputNodes = config.getArray("input");
|
||||
mInputNodes = new int[inputNodes.size()];
|
||||
@@ -43,8 +41,8 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
}
|
||||
mValue -= ((ValueAnimatedNode) animatedNode).getValue();
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException("Illegal node ID set as an input for " +
|
||||
"Animated.subtract node");
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for " + "Animated.subtract node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
@@ -30,6 +29,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
public void update() {
|
||||
AnimatedNode toValue = mNativeAnimatedNodesManager.getNodeById(mToValueNode);
|
||||
mAnimationConfig.putDouble("toValue", ((ValueAnimatedNode) toValue).getValue());
|
||||
mNativeAnimatedNodesManager.startAnimatingNode(mAnimationId, mValueNode, mAnimationConfig, null);
|
||||
mNativeAnimatedNodesManager.startAnimatingNode(
|
||||
mAnimationId, mValueNode, mAnimationConfig, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.JavaOnlyMap;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Native counterpart of transform animated node (see AnimatedTransform class in AnimatedImplementation.js)
|
||||
* Native counterpart of transform animated node (see AnimatedTransform class in
|
||||
* AnimatedImplementation.js)
|
||||
*/
|
||||
/* package */ class TransformAnimatedNode extends AnimatedNode {
|
||||
|
||||
@@ -70,8 +69,8 @@ import java.util.List;
|
||||
} else if (node instanceof ValueAnimatedNode) {
|
||||
value = ((ValueAnimatedNode) node).getValue();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported type of node used as a transform child " +
|
||||
"node " + node.getClass());
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported type of node used as a transform child " + "node " + node.getClass());
|
||||
}
|
||||
} else {
|
||||
value = ((StaticTransformConfig) transformConfig).mValue;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.animated;
|
||||
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,13 +14,9 @@ import android.content.Intent;
|
||||
*/
|
||||
public interface ActivityEventListener {
|
||||
|
||||
/**
|
||||
* Called when host (activity/service) receives an {@link Activity#onActivityResult} call.
|
||||
*/
|
||||
/** Called when host (activity/service) receives an {@link Activity#onActivityResult} call. */
|
||||
void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data);
|
||||
|
||||
/**
|
||||
* Called when a new intent is passed to the activity
|
||||
*/
|
||||
/** Called when a new intent is passed to the activity */
|
||||
void onNewIntent(Intent intent);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.os.Bundle;
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class Arguments {
|
||||
private static Object makeNativeObject(Object object) {
|
||||
if (object == null) {
|
||||
return null;
|
||||
} else if (object instanceof Float ||
|
||||
object instanceof Long ||
|
||||
object instanceof Byte ||
|
||||
object instanceof Short) {
|
||||
} else if (object instanceof Float
|
||||
|| object instanceof Long
|
||||
|| object instanceof Byte
|
||||
|| object instanceof Short) {
|
||||
return ((Number) object).doubleValue();
|
||||
} else if (object.getClass().isArray()) {
|
||||
return makeNativeArray(object);
|
||||
@@ -41,12 +38,11 @@ public class Arguments {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a List into a NativeArray. The data types supported
|
||||
* are boolean, int, float, double, and String. List, Map, and Bundle
|
||||
* objects, as well as arrays, containing values of the above types and/or
|
||||
* null, or any recursive arrangement of these, are also supported. The best
|
||||
* way to think of this is a way to generate a Java representation of a json
|
||||
* list, from Java types which have a natural representation in json.
|
||||
* This method converts a List into a NativeArray. The data types supported are boolean, int,
|
||||
* float, double, and String. List, Map, and Bundle objects, as well as arrays, containing values
|
||||
* of the above types and/or null, or any recursive arrangement of these, are also supported. The
|
||||
* best way to think of this is a way to generate a Java representation of a json list, from Java
|
||||
* types which have a natural representation in json.
|
||||
*/
|
||||
public static WritableNativeArray makeNativeArray(List objects) {
|
||||
WritableNativeArray nativeArray = new WritableNativeArray();
|
||||
@@ -77,8 +73,8 @@ public class Arguments {
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload is like the above, but uses reflection to operate on any
|
||||
* primitive or object type.
|
||||
* This overload is like the above, but uses reflection to operate on any primitive or object
|
||||
* type.
|
||||
*/
|
||||
public static <T> WritableNativeArray makeNativeArray(final Object objects) {
|
||||
if (objects == null) {
|
||||
@@ -86,15 +82,16 @@ public class Arguments {
|
||||
}
|
||||
// No explicit check for objects's type here. If it's not an array, the
|
||||
// Array methods will throw IllegalArgumentException.
|
||||
return makeNativeArray(new AbstractList() {
|
||||
public int size() {
|
||||
return Array.getLength(objects);
|
||||
}
|
||||
return makeNativeArray(
|
||||
new AbstractList() {
|
||||
public int size() {
|
||||
return Array.getLength(objects);
|
||||
}
|
||||
|
||||
public Object get(int index) {
|
||||
return Array.get(objects, index);
|
||||
}
|
||||
});
|
||||
public Object get(int index) {
|
||||
return Array.get(objects, index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void addEntry(WritableNativeMap nativeMap, String key, Object value) {
|
||||
@@ -119,10 +116,9 @@ public class Arguments {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a Map into a NativeMap. Value types are supported as
|
||||
* with makeNativeArray. The best way to think of this is a way to generate
|
||||
* a Java representation of a json object, from Java types which have a
|
||||
* natural representation in json.
|
||||
* This method converts a Map into a NativeMap. Value types are supported as with makeNativeArray.
|
||||
* The best way to think of this is a way to generate a Java representation of a json object, from
|
||||
* Java types which have a natural representation in json.
|
||||
*/
|
||||
public static WritableNativeMap makeNativeMap(Map<String, Object> objects) {
|
||||
WritableNativeMap nativeMap = new WritableNativeMap();
|
||||
@@ -135,9 +131,7 @@ public class Arguments {
|
||||
return nativeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like the above, but takes a Bundle instead of a Map.
|
||||
*/
|
||||
/** Like the above, but takes a Bundle instead of a Map. */
|
||||
public static WritableNativeMap makeNativeMap(Bundle bundle) {
|
||||
WritableNativeMap nativeMap = new WritableNativeMap();
|
||||
if (bundle == null) {
|
||||
@@ -149,16 +143,12 @@ public class Arguments {
|
||||
return nativeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be used when you need to stub out creating NativeArrays in unit tests.
|
||||
*/
|
||||
/** This method should be used when you need to stub out creating NativeArrays in unit tests. */
|
||||
public static WritableArray createArray() {
|
||||
return new WritableNativeArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be used when you need to stub out creating NativeMaps in unit tests.
|
||||
*/
|
||||
/** This method should be used when you need to stub out creating NativeMaps in unit tests. */
|
||||
public static WritableMap createMap() {
|
||||
return new WritableNativeMap();
|
||||
}
|
||||
@@ -198,7 +188,7 @@ public class Arguments {
|
||||
* Convert an array to a {@link WritableArray}.
|
||||
*
|
||||
* @param array the array to convert. Supported types are: {@code String[]}, {@code Bundle[]},
|
||||
* {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}.
|
||||
* {@code int[]}, {@code float[]}, {@code double[]}, {@code boolean[]}.
|
||||
* @return the converted {@link WritableArray}
|
||||
* @throws IllegalArgumentException if the passed object is none of the above types
|
||||
*/
|
||||
@@ -237,10 +227,12 @@ public class Arguments {
|
||||
/**
|
||||
* Convert a {@link List} to a {@link WritableArray}.
|
||||
*
|
||||
* @param list the list to convert. Supported value types are: {@code null}, {@code String}, {@code Bundle},
|
||||
* {@code List}, {@code Number}, {@code Boolean}, and all array types supported in {@link #fromArray(Object)}.
|
||||
* @param list the list to convert. Supported value types are: {@code null}, {@code String},
|
||||
* {@code Bundle}, {@code List}, {@code Number}, {@code Boolean}, and all array types
|
||||
* supported in {@link #fromArray(Object)}.
|
||||
* @return the converted {@link WritableArray}
|
||||
* @throws IllegalArgumentException if one of the values from the passed list is none of the above types
|
||||
* @throws IllegalArgumentException if one of the values from the passed list is none of the above
|
||||
* types
|
||||
*/
|
||||
public static WritableArray fromList(List list) {
|
||||
WritableArray catalystArray = createArray();
|
||||
@@ -269,14 +261,15 @@ public class Arguments {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle
|
||||
* are:
|
||||
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle are:
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>primitive types: int, float, double, boolean</li>
|
||||
* <li>arrays supported by {@link #fromArray(Object)}</li>
|
||||
* <li>lists supported by {@link #fromList(List)}</li>
|
||||
* <li>{@link Bundle} objects that are recursively converted to maps</li>
|
||||
* <li>primitive types: int, float, double, boolean
|
||||
* <li>arrays supported by {@link #fromArray(Object)}
|
||||
* <li>lists supported by {@link #fromList(List)}
|
||||
* <li>{@link Bundle} objects that are recursively converted to maps
|
||||
* </ul>
|
||||
*
|
||||
* @param bundle the {@link Bundle} to convert
|
||||
@@ -362,8 +355,8 @@ public class Arguments {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link WritableMap} to a {@link Bundle}.
|
||||
* Note: Each array is converted to an {@link ArrayList}.
|
||||
* Convert a {@link WritableMap} to a {@link Bundle}. Note: Each array is converted to an {@link
|
||||
* ArrayList}.
|
||||
*
|
||||
* @param readableMap the {@link WritableMap} to convert.
|
||||
* @return the converted {@link Bundle}.
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Like {@link AssertionError} but extends RuntimeException so that it may be caught by a
|
||||
* {@link NativeModuleCallExceptionHandler}. See that class for more details. Used in
|
||||
* conjunction with {@link SoftAssertions}.
|
||||
* Like {@link AssertionError} but extends RuntimeException so that it may be caught by a {@link
|
||||
* NativeModuleCallExceptionHandler}. See that class for more details. Used in conjunction with
|
||||
* {@link SoftAssertions}.
|
||||
*/
|
||||
public class AssertionException extends RuntimeException {
|
||||
|
||||
|
||||
@@ -8,20 +8,16 @@ package com.facebook.react.bridge;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* An empty implementation of {@link ActivityEventListener}
|
||||
*/
|
||||
/** An empty implementation of {@link ActivityEventListener} */
|
||||
public class BaseActivityEventListener implements ActivityEventListener {
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #onActivityResult(Activity, int, int, Intent)} instead.
|
||||
*/
|
||||
/** @deprecated use {@link #onActivityResult(Activity, int, int, Intent)} instead. */
|
||||
@Deprecated
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) { }
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { }
|
||||
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) { }
|
||||
public void onNewIntent(Intent intent) {}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,44 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 javax.annotation.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for Catalyst native modules whose implementations are written in Java. Default
|
||||
* implementations for {@link #initialize} and {@link #onCatalystInstanceDestroy} are provided for
|
||||
* convenience. Subclasses which override these don't need to call {@code super} in case of
|
||||
* convenience. Subclasses which override these don't need to call {@code super} in case of
|
||||
* overriding those methods as implementation of those methods is empty.
|
||||
*
|
||||
* BaseJavaModules can be linked to Fragments' lifecycle events, {@link CatalystInstance} creation
|
||||
* and destruction, by being called on the appropriate method when a life cycle event occurs.
|
||||
* <p>BaseJavaModules can be linked to Fragments' lifecycle events, {@link CatalystInstance}
|
||||
* creation and destruction, by being called on the appropriate method when a life cycle event
|
||||
* occurs.
|
||||
*
|
||||
* Native methods can be exposed to JS with {@link ReactMethod} annotation. Those methods may
|
||||
* only use limited number of types for their arguments:
|
||||
* 1/ primitives (boolean, int, float, double
|
||||
* 2/ {@link String} mapped from JS string
|
||||
* 3/ {@link ReadableArray} mapped from JS Array
|
||||
* 4/ {@link ReadableMap} mapped from JS Object
|
||||
* 5/ {@link Callback} mapped from js function and can be used only as a last parameter or in the
|
||||
* case when it express success & error callback pair as two last arguments respectively.
|
||||
* <p>Native methods can be exposed to JS with {@link ReactMethod} annotation. Those methods may
|
||||
* only use limited number of types for their arguments: 1/ primitives (boolean, int, float, double
|
||||
* 2/ {@link String} mapped from JS string 3/ {@link ReadableArray} mapped from JS Array 4/ {@link
|
||||
* ReadableMap} mapped from JS Object 5/ {@link Callback} mapped from js function and can be used
|
||||
* only as a last parameter or in the case when it express success & error callback pair as two last
|
||||
* arguments respectively.
|
||||
*
|
||||
* All methods exposed as native to JS with {@link ReactMethod} annotation must return
|
||||
* {@code void}.
|
||||
* <p>All methods exposed as native to JS with {@link ReactMethod} annotation must return {@code
|
||||
* void}.
|
||||
*
|
||||
* Please note that it is not allowed to have multiple methods annotated with {@link ReactMethod}
|
||||
* <p>Please note that it is not allowed to have multiple methods annotated with {@link ReactMethod}
|
||||
* with the same name.
|
||||
*/
|
||||
public abstract class BaseJavaModule implements NativeModule {
|
||||
// taken from Libraries/Utilities/MessageQueue.js
|
||||
static final public String METHOD_TYPE_ASYNC = "async";
|
||||
static final public String METHOD_TYPE_PROMISE= "promise";
|
||||
static final public String METHOD_TYPE_SYNC = "sync";
|
||||
public static final String METHOD_TYPE_ASYNC = "async";
|
||||
public static final String METHOD_TYPE_PROMISE = "promise";
|
||||
public static final String METHOD_TYPE_SYNC = "sync";
|
||||
|
||||
/**
|
||||
* @return a map of constants this module exports to JS. Supports JSON types.
|
||||
*/
|
||||
/** @return a map of constants this module exports to JS. Supports JSON types. */
|
||||
public @Nullable Map<String, Object> getConstants() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Interface that represent javascript callback function which can be passed to the native module
|
||||
* as a method parameter.
|
||||
* Interface that represent javascript callback function which can be passed to the native module as
|
||||
* a method parameter.
|
||||
*/
|
||||
public interface Callback {
|
||||
|
||||
@@ -19,5 +18,4 @@ public interface Callback {
|
||||
* @param args arguments passed to javascript callback method via bridge
|
||||
*/
|
||||
public void invoke(Object... args);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Implementation of javascript callback function that use Bridge to schedule method execution
|
||||
*/
|
||||
/** Implementation of javascript callback function that use Bridge to schedule method execution */
|
||||
public final class CallbackImpl implements Callback {
|
||||
|
||||
private final JSInstance mJSInstance;
|
||||
@@ -25,9 +22,10 @@ public final class CallbackImpl implements Callback {
|
||||
@Override
|
||||
public void invoke(Object... args) {
|
||||
if (mInvoked) {
|
||||
throw new RuntimeException("Illegal callback invocation from native "+
|
||||
"module. This callback type only permits a single invocation from "+
|
||||
"native code.");
|
||||
throw new RuntimeException(
|
||||
"Illegal callback invocation from native "
|
||||
+ "module. This callback type only permits a single invocation from "
|
||||
+ "native code.");
|
||||
}
|
||||
mJSInstance.invokeCallback(mCallbackId, Arguments.fromJavaArgs(args));
|
||||
mInvoked = true;
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.turbomodule.core.interfaces.JSCallInvokerHolder;
|
||||
import com.facebook.react.turbomodule.core.interfaces.TurboModuleRegistry;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A higher level API on top of the asynchronous JSC bridge. This provides an
|
||||
* environment allowing the invocation of JavaScript methods and lets a set of
|
||||
* Java APIs be invokable from JavaScript as well.
|
||||
* A higher level API on top of the asynchronous JSC bridge. This provides an environment allowing
|
||||
* the invocation of JavaScript methods and lets a set of Java APIs be invokable from JavaScript as
|
||||
* well.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public interface CatalystInstance
|
||||
@@ -30,48 +28,50 @@ public interface CatalystInstance
|
||||
boolean hasRunJSBundle();
|
||||
|
||||
/**
|
||||
* Return the source URL of the JS Bundle that was run, or {@code null} if no JS
|
||||
* bundle has been run yet.
|
||||
* Return the source URL of the JS Bundle that was run, or {@code null} if no JS bundle has been
|
||||
* run yet.
|
||||
*/
|
||||
@Nullable String getSourceURL();
|
||||
@Nullable
|
||||
String getSourceURL();
|
||||
|
||||
// This is called from java code, so it won't be stripped anyway, but proguard will rename it,
|
||||
// which this prevents.
|
||||
@Override @DoNotStrip
|
||||
void invokeCallback(
|
||||
int callbackID,
|
||||
NativeArrayInterface arguments);
|
||||
@Override
|
||||
@DoNotStrip
|
||||
void callFunction(
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments);
|
||||
void invokeCallback(int callbackID, NativeArrayInterface arguments);
|
||||
|
||||
@DoNotStrip
|
||||
void callFunction(String module, String method, NativeArray arguments);
|
||||
/**
|
||||
* Destroys this catalyst instance, waiting for any other threads in ReactQueueConfiguration
|
||||
* (besides the UI thread) to finish running. Must be called from the UI thread so that we can
|
||||
* fully shut down other threads.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
boolean isDestroyed();
|
||||
|
||||
/**
|
||||
* Initialize all the native modules
|
||||
*/
|
||||
/** Initialize all the native modules */
|
||||
@VisibleForTesting
|
||||
void initialize();
|
||||
|
||||
ReactQueueConfiguration getReactQueueConfiguration();
|
||||
|
||||
<T extends JavaScriptModule> T getJSModule(Class<T> jsInterface);
|
||||
|
||||
<T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface);
|
||||
|
||||
<T extends NativeModule> T getNativeModule(Class<T> nativeModuleInterface);
|
||||
|
||||
NativeModule getNativeModule(String moduleName);
|
||||
|
||||
JSIModule getJSIModule(JSIModuleType moduleType);
|
||||
|
||||
Collection<NativeModule> getNativeModules();
|
||||
|
||||
/**
|
||||
* This method permits a CatalystInstance to extend the known
|
||||
* Native modules. This provided registry contains only the new modules to load.
|
||||
* This method permits a CatalystInstance to extend the known Native modules. This provided
|
||||
* registry contains only the new modules to load.
|
||||
*/
|
||||
void extendNativeModules(NativeModuleRegistry modules);
|
||||
|
||||
@@ -84,8 +84,8 @@ public interface CatalystInstance
|
||||
void addBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener);
|
||||
|
||||
/**
|
||||
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with
|
||||
* {@link #addBridgeIdleDebugListener}
|
||||
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link
|
||||
* #addBridgeIdleDebugListener}
|
||||
*/
|
||||
void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener);
|
||||
|
||||
@@ -107,16 +107,15 @@ public interface CatalystInstance
|
||||
void addJSIModules(List<JSIModuleSpec> jsiModules);
|
||||
|
||||
/**
|
||||
* Returns a hybrid object that contains a pointer to JSCallInvoker.
|
||||
* Required for TurboModuleManager initialization.
|
||||
* Returns a hybrid object that contains a pointer to JSCallInvoker. Required for
|
||||
* TurboModuleManager initialization.
|
||||
*/
|
||||
JSCallInvokerHolder getJSCallInvokerHolder();
|
||||
|
||||
/**
|
||||
* For the time being, we want code relying on the old infra to also
|
||||
* work with TurboModules. Hence, we must provide the TurboModuleRegistry
|
||||
* to CatalystInstance so that getNativeModule, hasNativeModule, and
|
||||
* getNativeModules can also return TurboModules.
|
||||
* For the time being, we want code relying on the old infra to also work with TurboModules.
|
||||
* Hence, we must provide the TurboModuleRegistry to CatalystInstance so that getNativeModule,
|
||||
* hasNativeModule, and getNativeModules can also return TurboModules.
|
||||
*/
|
||||
void setTurboModuleManager(JSIModule getter);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
@@ -38,8 +37,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This provides an implementation of the public CatalystInstance instance. It is public because
|
||||
* it is built by XReactInstanceManager which is in a different package.
|
||||
* This provides an implementation of the public CatalystInstance instance. It is public because it
|
||||
* is built by XReactInstanceManager which is in a different package.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class CatalystInstanceImpl implements CatalystInstance {
|
||||
@@ -67,8 +66,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return mModule + "." + mMethod + "("
|
||||
+ (mArguments == null ? "" : mArguments.toString()) + ")";
|
||||
return mModule
|
||||
+ "."
|
||||
+ mMethod
|
||||
+ "("
|
||||
+ (mArguments == null ? "" : mArguments.toString())
|
||||
+ ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +103,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
|
||||
// C++ parts
|
||||
private final HybridData mHybridData;
|
||||
private native static HybridData initHybrid();
|
||||
|
||||
private static native HybridData initHybrid();
|
||||
|
||||
public native JSCallInvokerHolderImpl getJSCallInvokerHolder();
|
||||
|
||||
private CatalystInstanceImpl(
|
||||
@@ -114,9 +119,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
|
||||
mHybridData = initHybrid();
|
||||
|
||||
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
|
||||
reactQueueConfigurationSpec,
|
||||
new NativeExceptionHandler());
|
||||
mReactQueueConfiguration =
|
||||
ReactQueueConfigurationImpl.create(
|
||||
reactQueueConfigurationSpec, new NativeExceptionHandler());
|
||||
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
|
||||
mNativeModuleRegistry = nativeModuleRegistry;
|
||||
mJSModuleRegistry = new JavaScriptModuleRegistry();
|
||||
@@ -129,12 +134,12 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge before initializeBridge");
|
||||
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initializeCxxBridge");
|
||||
initializeBridge(
|
||||
new BridgeCallback(this),
|
||||
jsExecutor,
|
||||
mReactQueueConfiguration.getJSQueueThread(),
|
||||
mNativeModulesQueueThread,
|
||||
mNativeModuleRegistry.getJavaModules(this),
|
||||
mNativeModuleRegistry.getCxxModules());
|
||||
new BridgeCallback(this),
|
||||
jsExecutor,
|
||||
mReactQueueConfiguration.getJSQueueThread(),
|
||||
mNativeModulesQueueThread,
|
||||
mNativeModuleRegistry.getJavaModules(this),
|
||||
mNativeModuleRegistry.getCxxModules());
|
||||
Log.d(ReactConstants.TAG, "Initializing React Xplat Bridge after initializeBridge");
|
||||
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
|
||||
@@ -177,24 +182,23 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method and the native below permits a CatalystInstance to extend the known
|
||||
* Native modules. This registry contains only the new modules to load. The
|
||||
* registry {@code mNativeModuleRegistry} updates internally to contain all the new modules, and generates
|
||||
* the new registry for extracting just the new collections.
|
||||
* This method and the native below permits a CatalystInstance to extend the known Native modules.
|
||||
* This registry contains only the new modules to load. The registry {@code mNativeModuleRegistry}
|
||||
* updates internally to contain all the new modules, and generates the new registry for
|
||||
* extracting just the new collections.
|
||||
*/
|
||||
@Override
|
||||
public void extendNativeModules(NativeModuleRegistry modules) {
|
||||
//Extend the Java-visible registry of modules
|
||||
// Extend the Java-visible registry of modules
|
||||
mNativeModuleRegistry.registerModules(modules);
|
||||
Collection<JavaModuleWrapper> javaModules = modules.getJavaModules(this);
|
||||
Collection<ModuleHolder> cxxModules = modules.getCxxModules();
|
||||
//Extend the Cxx-visible registry of modules wrapped in appropriate interfaces
|
||||
// Extend the Cxx-visible registry of modules wrapped in appropriate interfaces
|
||||
jniExtendNativeModules(javaModules, cxxModules);
|
||||
}
|
||||
|
||||
private native void jniExtendNativeModules(
|
||||
Collection<JavaModuleWrapper> javaModules,
|
||||
Collection<ModuleHolder> cxxModules);
|
||||
Collection<JavaModuleWrapper> javaModules, Collection<ModuleHolder> cxxModules);
|
||||
|
||||
private native void initializeBridge(
|
||||
ReactCallback callback,
|
||||
@@ -216,7 +220,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously) {
|
||||
public void loadScriptFromAssets(
|
||||
AssetManager assetManager, String assetURL, boolean loadSynchronously) {
|
||||
mSourceURL = assetURL;
|
||||
jniLoadScriptFromAssets(assetManager, assetURL, loadSynchronously);
|
||||
}
|
||||
@@ -229,18 +234,23 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
|
||||
@Override
|
||||
public void loadScriptFromDeltaBundle(
|
||||
String sourceURL,
|
||||
NativeDeltaClient deltaClient,
|
||||
boolean loadSynchronously) {
|
||||
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously) {
|
||||
mSourceURL = sourceURL;
|
||||
jniLoadScriptFromDeltaBundle(sourceURL, deltaClient, loadSynchronously);
|
||||
}
|
||||
|
||||
private native void jniSetSourceURL(String sourceURL);
|
||||
|
||||
private native void jniRegisterSegment(int segmentId, String path);
|
||||
private native void jniLoadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);
|
||||
private native void jniLoadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);
|
||||
private native void jniLoadScriptFromDeltaBundle(String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
|
||||
|
||||
private native void jniLoadScriptFromAssets(
|
||||
AssetManager assetManager, String assetURL, boolean loadSynchronously);
|
||||
|
||||
private native void jniLoadScriptFromFile(
|
||||
String fileName, String sourceURL, boolean loadSynchronously);
|
||||
|
||||
private native void jniLoadScriptFromDeltaBundle(
|
||||
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
|
||||
|
||||
@Override
|
||||
public void runJSBundle() {
|
||||
@@ -279,16 +289,10 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
return mSourceURL;
|
||||
}
|
||||
|
||||
private native void jniCallJSFunction(
|
||||
String module,
|
||||
String method,
|
||||
NativeArray arguments);
|
||||
private native void jniCallJSFunction(String module, String method, NativeArray arguments);
|
||||
|
||||
@Override
|
||||
public void callFunction(
|
||||
final String module,
|
||||
final String method,
|
||||
final NativeArray arguments) {
|
||||
public void callFunction(final String module, final String method, final NativeArray arguments) {
|
||||
callFunction(new PendingJSCall(module, method, arguments));
|
||||
}
|
||||
|
||||
@@ -385,29 +389,25 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
return mDestroyed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all the native modules
|
||||
*/
|
||||
/** Initialize all the native modules */
|
||||
@VisibleForTesting
|
||||
@Override
|
||||
public void initialize() {
|
||||
Log.d(ReactConstants.TAG, "CatalystInstanceImpl.initialize()");
|
||||
Assertions.assertCondition(
|
||||
!mInitialized,
|
||||
"This catalyst instance has already been initialized");
|
||||
!mInitialized, "This catalyst instance has already been initialized");
|
||||
// We assume that the instance manager blocks on running the JS bundle. If
|
||||
// that changes, then we need to set mAcceptCalls just after posting the
|
||||
// task that will run the js bundle.
|
||||
Assertions.assertCondition(
|
||||
mAcceptCalls,
|
||||
"RunJSBundle hasn't completed.");
|
||||
Assertions.assertCondition(mAcceptCalls, "RunJSBundle hasn't completed.");
|
||||
mInitialized = true;
|
||||
mNativeModulesQueueThread.runOnQueue(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mNativeModuleRegistry.notifyJSInstanceInitialized();
|
||||
}
|
||||
});
|
||||
mNativeModulesQueueThread.runOnQueue(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mNativeModuleRegistry.notifyJSInstanceInitialized();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -423,7 +423,9 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
@Override
|
||||
public <T extends NativeModule> boolean hasNativeModule(Class<T> nativeModuleInterface) {
|
||||
String moduleName = getNameFromAnnotation(nativeModuleInterface);
|
||||
return mTurboModuleRegistry != null && mTurboModuleRegistry.hasModule(moduleName) ? true : mNativeModuleRegistry.hasModule(moduleName);
|
||||
return mTurboModuleRegistry != null && mTurboModuleRegistry.hasModule(moduleName)
|
||||
? true
|
||||
: mNativeModuleRegistry.hasModule(moduleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -437,17 +439,18 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
TurboModule turboModule = mTurboModuleRegistry.getModule(moduleName);
|
||||
|
||||
if (turboModule != null) {
|
||||
return (NativeModule)turboModule;
|
||||
return (NativeModule) turboModule;
|
||||
}
|
||||
}
|
||||
|
||||
return mNativeModuleRegistry.getModule(moduleName);
|
||||
}
|
||||
|
||||
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface){
|
||||
private <T extends NativeModule> String getNameFromAnnotation(Class<T> nativeModuleInterface) {
|
||||
ReactModule annotation = nativeModuleInterface.getAnnotation(ReactModule.class);
|
||||
if (annotation == null) {
|
||||
throw new IllegalArgumentException("Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
|
||||
throw new IllegalArgumentException(
|
||||
"Could not find @ReactModule annotation in " + nativeModuleInterface.getCanonicalName());
|
||||
}
|
||||
return annotation.name();
|
||||
}
|
||||
@@ -489,8 +492,8 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with
|
||||
* {@link #addBridgeIdleDebugListener}
|
||||
* Removes a NotThreadSafeBridgeIdleDebugListener previously added with {@link
|
||||
* #addBridgeIdleDebugListener}
|
||||
*/
|
||||
@Override
|
||||
public void removeBridgeIdleDebugListener(NotThreadSafeBridgeIdleDebugListener listener) {
|
||||
@@ -521,56 +524,56 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
int oldPendingCalls = mPendingJSCalls.getAndIncrement();
|
||||
boolean wasIdle = oldPendingCalls == 0;
|
||||
Systrace.traceCounter(
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
|
||||
mJsPendingCallsTitleForTrace,
|
||||
oldPendingCalls + 1);
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, oldPendingCalls + 1);
|
||||
if (wasIdle && !mBridgeIdleListeners.isEmpty()) {
|
||||
mNativeModulesQueueThread.runOnQueue(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
|
||||
listener.onTransitionToBridgeBusy();
|
||||
}
|
||||
}
|
||||
});
|
||||
mNativeModulesQueueThread.runOnQueue(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
|
||||
listener.onTransitionToBridgeBusy();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setTurboModuleManager(JSIModule getter) {
|
||||
mTurboModuleRegistry = (TurboModuleRegistry)getter;
|
||||
mTurboModuleRegistry = (TurboModuleRegistry) getter;
|
||||
}
|
||||
|
||||
private void decrementPendingJSCalls() {
|
||||
int newPendingCalls = mPendingJSCalls.decrementAndGet();
|
||||
// TODO(9604406): handle case of web workers injecting messages to main thread
|
||||
//Assertions.assertCondition(newPendingCalls >= 0);
|
||||
// Assertions.assertCondition(newPendingCalls >= 0);
|
||||
boolean isNowIdle = newPendingCalls == 0;
|
||||
Systrace.traceCounter(
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
|
||||
mJsPendingCallsTitleForTrace,
|
||||
newPendingCalls);
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, newPendingCalls);
|
||||
|
||||
if (isNowIdle && !mBridgeIdleListeners.isEmpty()) {
|
||||
mNativeModulesQueueThread.runOnQueue(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
|
||||
listener.onTransitionToBridgeIdle();
|
||||
}
|
||||
}
|
||||
});
|
||||
mNativeModulesQueueThread.runOnQueue(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
|
||||
listener.onTransitionToBridgeIdle();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void onNativeException(Exception e) {
|
||||
mNativeModuleCallExceptionHandler.handleException(e);
|
||||
mReactQueueConfiguration.getUIQueueThread().runOnQueue(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
destroy();
|
||||
}
|
||||
});
|
||||
mReactQueueConfiguration
|
||||
.getUIQueueThread()
|
||||
.runOnQueue(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class NativeExceptionHandler implements QueueThreadExceptionHandler {
|
||||
@@ -619,7 +622,6 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
private @Nullable JavaScriptExecutor mJSExecutor;
|
||||
private @Nullable NativeModuleCallExceptionHandler mNativeModuleCallExceptionHandler;
|
||||
|
||||
|
||||
public Builder setReactQueueConfigurationSpec(
|
||||
ReactQueueConfigurationSpec ReactQueueConfigurationSpec) {
|
||||
mReactQueueConfigurationSpec = ReactQueueConfigurationSpec;
|
||||
@@ -641,8 +643,7 @@ public class CatalystInstanceImpl implements CatalystInstance {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNativeModuleCallExceptionHandler(
|
||||
NativeModuleCallExceptionHandler handler) {
|
||||
public Builder setNativeModuleCallExceptionHandler(NativeModuleCallExceptionHandler handler) {
|
||||
mNativeModuleCallExceptionHandler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.content.Context;
|
||||
|
||||
/**
|
||||
* Base class for React native modules that require access to an Android
|
||||
* {@link Context} instance.
|
||||
* Base class for React native modules that require access to an Android {@link Context} instance.
|
||||
*/
|
||||
public abstract class ContextBaseJavaModule extends BaseJavaModule {
|
||||
|
||||
@@ -21,9 +19,7 @@ public abstract class ContextBaseJavaModule extends BaseJavaModule {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can use this method to access Android context passed as a constructor
|
||||
*/
|
||||
/** Subclasses can use this method to access Android context passed as a constructor */
|
||||
protected final Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@@ -5,20 +5,15 @@
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.NativeArray;
|
||||
|
||||
import static com.facebook.react.bridge.Arguments.*;
|
||||
|
||||
/**
|
||||
* Callback impl that calls directly into the cxx bridge. Created from C++.
|
||||
*/
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/** Callback impl that calls directly into the cxx bridge. Created from C++. */
|
||||
@DoNotStrip
|
||||
public class CxxCallbackImpl implements Callback {
|
||||
@DoNotStrip
|
||||
private final HybridData mHybridData;
|
||||
@DoNotStrip private final HybridData mHybridData;
|
||||
|
||||
@DoNotStrip
|
||||
private CxxCallbackImpl(HybridData hybridData) {
|
||||
|
||||
@@ -9,12 +9,9 @@ import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* This does nothing interesting, except avoid breaking existing code.
|
||||
*/
|
||||
/** This does nothing interesting, except avoid breaking existing code. */
|
||||
@DoNotStrip
|
||||
public class CxxModuleWrapper extends CxxModuleWrapperBase
|
||||
{
|
||||
public class CxxModuleWrapper extends CxxModuleWrapperBase {
|
||||
protected CxxModuleWrapper(HybridData hd) {
|
||||
super(hd);
|
||||
}
|
||||
|
||||
@@ -11,18 +11,16 @@ import com.facebook.proguard.annotations.DoNotStrip;
|
||||
/**
|
||||
* A Java Object which represents a cross-platform C++ module
|
||||
*
|
||||
* This module implements the NativeModule interface but will never be invoked from Java,
|
||||
* instead the underlying Cxx module will be extracted by the bridge and called directly.
|
||||
* <p>This module implements the NativeModule interface but will never be invoked from Java, instead
|
||||
* the underlying Cxx module will be extracted by the bridge and called directly.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class CxxModuleWrapperBase implements NativeModule
|
||||
{
|
||||
public class CxxModuleWrapperBase implements NativeModule {
|
||||
static {
|
||||
ReactBridge.staticInit();
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
private HybridData mHybridData;
|
||||
@DoNotStrip private HybridData mHybridData;
|
||||
|
||||
@Override
|
||||
public native String getName();
|
||||
|
||||
+3
-6
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Crashy crashy exception handler.
|
||||
*/
|
||||
/** Crashy crashy exception handler. */
|
||||
public class DefaultNativeModuleCallExceptionHandler implements NativeModuleCallExceptionHandler {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
@@ -13,12 +12,20 @@ package com.facebook.react.bridge;
|
||||
*/
|
||||
public interface Dynamic {
|
||||
boolean isNull();
|
||||
|
||||
boolean asBoolean();
|
||||
|
||||
double asDouble();
|
||||
|
||||
int asInt();
|
||||
|
||||
String asString();
|
||||
|
||||
ReadableArray asArray();
|
||||
|
||||
ReadableMap asMap();
|
||||
|
||||
ReadableType getType();
|
||||
|
||||
void recycle();
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 androidx.core.util.Pools;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.core.util.Pools;
|
||||
|
||||
/**
|
||||
* Implementation of Dynamic wrapping a ReadableArray.
|
||||
*/
|
||||
/** Implementation of Dynamic wrapping a ReadableArray. */
|
||||
public class DynamicFromArray implements Dynamic {
|
||||
private static final Pools.SimplePool<DynamicFromArray> sPool = new Pools.SimplePool<>(10);
|
||||
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 androidx.core.util.Pools.SimplePool;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.core.util.Pools.SimplePool;
|
||||
|
||||
/**
|
||||
* Implementation of Dynamic wrapping a ReadableMap.
|
||||
*/
|
||||
/** Implementation of Dynamic wrapping a ReadableMap. */
|
||||
public class DynamicFromMap implements Dynamic {
|
||||
private static final ThreadLocal<SimplePool<DynamicFromMap>> sPool = new ThreadLocal<SimplePool<DynamicFromMap>>() {
|
||||
@Override
|
||||
protected SimplePool<DynamicFromMap> initialValue() {
|
||||
return new SimplePool<>(10);
|
||||
}
|
||||
};
|
||||
private static final ThreadLocal<SimplePool<DynamicFromMap>> sPool =
|
||||
new ThreadLocal<SimplePool<DynamicFromMap>>() {
|
||||
@Override
|
||||
protected SimplePool<DynamicFromMap> initialValue() {
|
||||
return new SimplePool<>(10);
|
||||
}
|
||||
};
|
||||
|
||||
private @Nullable ReadableMap mMap;
|
||||
private @Nullable String mName;
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Implementation of Dynamic wrapping a ReadableArray.
|
||||
*/
|
||||
/** Implementation of Dynamic wrapping a ReadableArray. */
|
||||
public class DynamicFromObject implements Dynamic {
|
||||
private @Nullable Object mObject;
|
||||
|
||||
@@ -33,33 +30,33 @@ public class DynamicFromObject implements Dynamic {
|
||||
|
||||
@Override
|
||||
public boolean asBoolean() {
|
||||
return (boolean)mObject;
|
||||
return (boolean) mObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double asDouble() {
|
||||
return (double)mObject;
|
||||
return (double) mObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int asInt() {
|
||||
// Numbers from JS are always Doubles
|
||||
return ((Double)mObject).intValue();
|
||||
return ((Double) mObject).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return (String)mObject;
|
||||
return (String) mObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableArray asArray() {
|
||||
return (ReadableArray)mObject;
|
||||
return (ReadableArray) mObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadableMap asMap() {
|
||||
return (ReadableMap)mObject;
|
||||
return (ReadableMap) mObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.common.logging.FLog;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
|
||||
/**
|
||||
* FallbackJSBundleLoader
|
||||
*
|
||||
* An implementation of {@link JSBundleLoader} that will try to load from
|
||||
* multiple sources, falling back from one source to the next at load time
|
||||
* when an exception is thrown for a recoverable error.
|
||||
* <p>An implementation of {@link JSBundleLoader} that will try to load from multiple sources,
|
||||
* falling back from one source to the next at load time when an exception is thrown for a
|
||||
* recoverable error.
|
||||
*/
|
||||
public final class FallbackJSBundleLoader extends JSBundleLoader {
|
||||
|
||||
@@ -32,10 +30,7 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
|
||||
// Reasons why we fell-back on previous loaders, in order of occurrence.
|
||||
private final ArrayList<Exception> mRecoveredErrors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* @param loaders Loaders for the sources to try, in descending order of
|
||||
* preference.
|
||||
*/
|
||||
/** @param loaders Loaders for the sources to try, in descending order of preference. */
|
||||
public FallbackJSBundleLoader(List<JSBundleLoader> loaders) {
|
||||
mLoaders = new Stack();
|
||||
ListIterator<JSBundleLoader> it = loaders.listIterator(loaders.size());
|
||||
@@ -45,9 +40,9 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* This loader delegates to (and so behaves like) the currently preferred
|
||||
* loader. If that loader fails in a recoverable way and we fall back from it,
|
||||
* it is replaced by the next most preferred loader.
|
||||
* This loader delegates to (and so behaves like) the currently preferred loader. If that loader
|
||||
* fails in a recoverable way and we fall back from it, it is replaced by the next most preferred
|
||||
* loader.
|
||||
*/
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
@@ -71,8 +66,7 @@ public final class FallbackJSBundleLoader extends JSBundleLoader {
|
||||
return mLoaders.peek();
|
||||
}
|
||||
|
||||
RuntimeException fallbackException =
|
||||
new RuntimeException("No fallback options available");
|
||||
RuntimeException fallbackException = new RuntimeException("No fallback options available");
|
||||
|
||||
// Invariant: tail.getCause() == null
|
||||
Throwable tail = fallbackException;
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.os.AsyncTask;
|
||||
|
||||
/**
|
||||
* Abstract base for a AsyncTask that should have any RuntimeExceptions it throws
|
||||
* handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if
|
||||
* the app is in dev mode.
|
||||
* Abstract base for a AsyncTask that should have any RuntimeExceptions it throws handled by the
|
||||
* {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if the app is in
|
||||
* dev mode.
|
||||
*
|
||||
* This class doesn't allow doInBackground to return a results. If you need this
|
||||
* use GuardedResultAsyncTask instead.
|
||||
* <p>This class doesn't allow doInBackground to return a results. If you need this use
|
||||
* GuardedResultAsyncTask instead.
|
||||
*/
|
||||
public abstract class GuardedAsyncTask<Params, Progress>
|
||||
extends AsyncTask<Params, Progress, Void> {
|
||||
public abstract class GuardedAsyncTask<Params, Progress> extends AsyncTask<Params, Progress, Void> {
|
||||
|
||||
private final ReactContext mReactContext;
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import android.os.AsyncTask;
|
||||
* throws handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler}
|
||||
* registered if the app is in dev mode.
|
||||
*/
|
||||
public abstract class GuardedResultAsyncTask<Result>
|
||||
extends AsyncTask<Void, Void, Result> {
|
||||
public abstract class GuardedResultAsyncTask<Result> extends AsyncTask<Void, Void, Result> {
|
||||
|
||||
private final ReactContext mReactContext;
|
||||
|
||||
@@ -41,6 +40,6 @@ public abstract class GuardedResultAsyncTask<Result>
|
||||
}
|
||||
|
||||
protected abstract Result doInBackgroundGuarded();
|
||||
protected abstract void onPostExecuteGuarded(Result result);
|
||||
|
||||
protected abstract void onPostExecuteGuarded(Result result);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
/**
|
||||
* Abstract base for a Runnable that should have any RuntimeExceptions it throws
|
||||
* handled by the {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if
|
||||
* the app is in dev mode.
|
||||
* Abstract base for a Runnable that should have any RuntimeExceptions it throws handled by the
|
||||
* {@link com.facebook.react.bridge.NativeModuleCallExceptionHandler} registered if the app is in
|
||||
* dev mode.
|
||||
*/
|
||||
public abstract class GuardedRunnable implements Runnable {
|
||||
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
|
||||
package com.facebook.react.bridge;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@DoNotStrip
|
||||
public class Inspector {
|
||||
@@ -70,10 +69,7 @@ public class Inspector {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Page{" +
|
||||
"mId=" + mId +
|
||||
", mTitle='" + mTitle + '\'' +
|
||||
'}';
|
||||
return "Page{" + "mId=" + mId + ", mTitle='" + mTitle + '\'' + '}';
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
@@ -88,6 +84,7 @@ public class Inspector {
|
||||
public interface RemoteConnection {
|
||||
@DoNotStrip
|
||||
void onMessage(String message);
|
||||
|
||||
@DoNotStrip
|
||||
void onDisconnect();
|
||||
}
|
||||
@@ -97,6 +94,7 @@ public class Inspector {
|
||||
private final HybridData mHybridData;
|
||||
|
||||
public native void sendMessage(String message);
|
||||
|
||||
public native void disconnect();
|
||||
|
||||
private LocalConnection(HybridData hybridData) {
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/**
|
||||
* Exception thrown by {@link ReadableMapKeySetIterator#nextKey()} when the iterator tries
|
||||
* to iterate over elements after the end of the key set.
|
||||
* Exception thrown by {@link ReadableMapKeySetIterator#nextKey()} when the iterator tries to
|
||||
* iterate over elements after the end of the key set.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class InvalidIteratorException extends RuntimeException {
|
||||
|
||||
+10
-13
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 javax.annotation.Nullable;
|
||||
@@ -13,19 +12,18 @@ import javax.annotation.Nullable;
|
||||
* A special RuntimeException that should be thrown by native code if it has reached an exceptional
|
||||
* state due to a, or a sequence of, bad commands.
|
||||
*
|
||||
* A good rule of thumb for whether a native Exception should extend this interface is 1) Can a
|
||||
* <p>A good rule of thumb for whether a native Exception should extend this interface is 1) Can a
|
||||
* developer make a change or correction in JS to keep this Exception from being thrown? 2) Is the
|
||||
* app outside of this catalyst instance still in a good state to allow reloading and restarting
|
||||
* this catalyst instance?
|
||||
*
|
||||
* Examples where this class is appropriate to throw:
|
||||
* - JS tries to update a view with a tag that hasn't been created yet
|
||||
* - JS tries to show a static image that isn't in resources
|
||||
* - JS tries to use an unsupported view class
|
||||
* <p>Examples where this class is appropriate to throw: - JS tries to update a view with a tag that
|
||||
* hasn't been created yet - JS tries to show a static image that isn't in resources - JS tries to
|
||||
* use an unsupported view class
|
||||
*
|
||||
* Examples where this class **isn't** appropriate to throw:
|
||||
* - Failed to write to localStorage because disk is full
|
||||
* - Assertions about internal state (e.g. that child.getParent().indexOf(child) != -1)
|
||||
* <p>Examples where this class **isn't** appropriate to throw: - Failed to write to localStorage
|
||||
* because disk is full - Assertions about internal state (e.g. that
|
||||
* child.getParent().indexOf(child) != -1)
|
||||
*/
|
||||
public class JSApplicationCausedNativeException extends RuntimeException {
|
||||
|
||||
@@ -34,8 +32,7 @@ public class JSApplicationCausedNativeException extends RuntimeException {
|
||||
}
|
||||
|
||||
public JSApplicationCausedNativeException(
|
||||
@Nullable String detailMessage,
|
||||
@Nullable Throwable throwable) {
|
||||
@Nullable String detailMessage, @Nullable Throwable throwable) {
|
||||
super(detailMessage, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,15 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* An illegal argument Exception caused by an argument passed from JS.
|
||||
*/
|
||||
/** An illegal argument Exception caused by an argument passed from JS. */
|
||||
public class JSApplicationIllegalArgumentException extends JSApplicationCausedNativeException {
|
||||
|
||||
public JSApplicationIllegalArgumentException(String detailMessage) {
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.content.Context;
|
||||
import com.facebook.react.common.DebugServerException;
|
||||
|
||||
/**
|
||||
* A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate}
|
||||
* (e.g. {@link CatalystInstance}) to load a correct bundle through {@link ReactBridge}.
|
||||
* A class that stores JS bundle information and allows a {@link JSBundleLoaderDelegate} (e.g.
|
||||
* {@link CatalystInstance}) to load a correct bundle through {@link ReactBridge}.
|
||||
*/
|
||||
public abstract class JSBundleLoader {
|
||||
|
||||
@@ -22,9 +21,7 @@ public abstract class JSBundleLoader {
|
||||
* strings from java to native memory.
|
||||
*/
|
||||
public static JSBundleLoader createAssetLoader(
|
||||
final Context context,
|
||||
final String assetUrl,
|
||||
final boolean loadSynchronously) {
|
||||
final Context context, final String assetUrl, final boolean loadSynchronously) {
|
||||
return new JSBundleLoader() {
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
@@ -43,9 +40,7 @@ public abstract class JSBundleLoader {
|
||||
}
|
||||
|
||||
public static JSBundleLoader createFileLoader(
|
||||
final String fileName,
|
||||
final String assetUrl,
|
||||
final boolean loadSynchronously) {
|
||||
final String fileName, final String assetUrl, final boolean loadSynchronously) {
|
||||
return new JSBundleLoader() {
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
@@ -63,8 +58,7 @@ public abstract class JSBundleLoader {
|
||||
* work correctly and allows for source maps to correctly symbolize those.
|
||||
*/
|
||||
public static JSBundleLoader createCachedBundleFromNetworkLoader(
|
||||
final String sourceURL,
|
||||
final String cachedFileLocation) {
|
||||
final String sourceURL, final String cachedFileLocation) {
|
||||
return new JSBundleLoader() {
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
@@ -82,11 +76,11 @@ public abstract class JSBundleLoader {
|
||||
* This loader is used to load delta bundles from the dev server. We pass each delta message to
|
||||
* the loader and process it in C++. Passing it as a string leads to inefficiencies due to memory
|
||||
* copies, which will have to be addressed in a follow-up.
|
||||
*
|
||||
* @param nativeDeltaClient
|
||||
*/
|
||||
public static JSBundleLoader createDeltaFromNetworkLoader(
|
||||
final String sourceURL,
|
||||
final NativeDeltaClient nativeDeltaClient) {
|
||||
final String sourceURL, final NativeDeltaClient nativeDeltaClient) {
|
||||
return new JSBundleLoader() {
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
@@ -105,8 +99,7 @@ public abstract class JSBundleLoader {
|
||||
* the bundle from device as remote executor will have to do it anyway.
|
||||
*/
|
||||
public static JSBundleLoader createRemoteDebuggerBundleLoader(
|
||||
final String proxySourceURL,
|
||||
final String realSourceURL) {
|
||||
final String proxySourceURL, final String realSourceURL) {
|
||||
return new JSBundleLoader() {
|
||||
@Override
|
||||
public String loadScript(JSBundleLoaderDelegate delegate) {
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
/**
|
||||
* An interface for classes that initialize JavaScript using {@link JSBundleLoader}
|
||||
*/
|
||||
/** An interface for classes that initialize JavaScript using {@link JSBundleLoader} */
|
||||
public interface JSBundleLoaderDelegate {
|
||||
|
||||
/**
|
||||
* Load a JS bundle from Android assets. See {@link JSBundleLoader#createAssetLoader(Context, String, boolean)}
|
||||
* Load a JS bundle from Android assets. See {@link JSBundleLoader#createAssetLoader(Context,
|
||||
* String, boolean)}
|
||||
*
|
||||
* @param assetManager
|
||||
* @param assetURL
|
||||
* @param loadSynchronously
|
||||
@@ -24,8 +23,9 @@ public interface JSBundleLoaderDelegate {
|
||||
void loadScriptFromAssets(AssetManager assetManager, String assetURL, boolean loadSynchronously);
|
||||
|
||||
/**
|
||||
* Load a JS bundle from the filesystem.
|
||||
* See {@link JSBundleLoader#createFileLoader(String)} and {@link JSBundleLoader#createCachedBundleFromNetworkLoader(String, String)}
|
||||
* Load a JS bundle from the filesystem. See {@link JSBundleLoader#createFileLoader(String)} and
|
||||
* {@link JSBundleLoader#createCachedBundleFromNetworkLoader(String, String)}
|
||||
*
|
||||
* @param fileName
|
||||
* @param sourceURL
|
||||
* @param loadSynchronously
|
||||
@@ -33,26 +33,23 @@ public interface JSBundleLoaderDelegate {
|
||||
void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously);
|
||||
|
||||
/**
|
||||
* Load a delta bundle from Metro.
|
||||
* See {@link JSBundleLoader#createDeltaFromNetworkLoader(String, NativeDeltaClient)}
|
||||
* Load a delta bundle from Metro. See {@link JSBundleLoader#createDeltaFromNetworkLoader(String,
|
||||
* NativeDeltaClient)}
|
||||
*
|
||||
* @param sourceURL
|
||||
* @param deltaClient
|
||||
* @param loadSynchronously
|
||||
*/
|
||||
void loadScriptFromDeltaBundle(
|
||||
String sourceURL,
|
||||
NativeDeltaClient deltaClient,
|
||||
boolean loadSynchronously);
|
||||
String sourceURL, NativeDeltaClient deltaClient, boolean loadSynchronously);
|
||||
|
||||
/**
|
||||
* This API is used in situations where the JS bundle is being executed not on
|
||||
* the device, but on a host machine. In that case, we must provide two source
|
||||
* URLs for the JS bundle: One to be used on the device, and one to be used on
|
||||
* the remote debugging machine.
|
||||
* This API is used in situations where the JS bundle is being executed not on the device, but on
|
||||
* a host machine. In that case, we must provide two source URLs for the JS bundle: One to be used
|
||||
* on the device, and one to be used on the remote debugging machine.
|
||||
*
|
||||
* @param deviceURL A source URL that is accessible from this device.
|
||||
* @param remoteURL A source URL that is accessible from the remote machine
|
||||
* executing the JS.
|
||||
* @param remoteURL A source URL that is accessible from the remote machine executing the JS.
|
||||
*/
|
||||
void setSourceURLs(String deviceURL, String remoteURL);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.jni.HybridData;
|
||||
@@ -25,6 +24,5 @@ import com.facebook.proguard.annotations.DoNotStrip;
|
||||
return "JSCJavaScriptExecutor";
|
||||
}
|
||||
|
||||
|
||||
private native static HybridData initHybrid(ReadableNativeMap jscConfig);
|
||||
private static native HybridData initHybrid(ReadableNativeMap jscConfig);
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
public class JSCJavaScriptExecutorFactory implements JavaScriptExecutorFactory {
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Marker interface used to represent a JSI Module.
|
||||
*/
|
||||
/** Marker interface used to represent a JSI Module. */
|
||||
public interface JSIModule {
|
||||
|
||||
/**
|
||||
* This is called at the end of {@link CatalystApplicationFragment#createCatalystInstance()}
|
||||
* after the CatalystInstance has been created, in order to initialize NativeModules that require
|
||||
* the CatalystInstance or JS modules.
|
||||
* This is called at the end of {@link CatalystApplicationFragment#createCatalystInstance()} after
|
||||
* the CatalystInstance has been created, in order to initialize NativeModules that require the
|
||||
* CatalystInstance or JS modules.
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Called before {CatalystInstance#onHostDestroy}
|
||||
*/
|
||||
/** Called before {CatalystInstance#onHostDestroy} */
|
||||
void onCatalystInstanceDestroy();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
public class JSIModuleHolder {
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 java.util.List;
|
||||
|
||||
/**
|
||||
* Interface used to initialize JSI Modules into the JSI Bridge.
|
||||
*/
|
||||
/** Interface used to initialize JSI Modules into the JSI Bridge. */
|
||||
public interface JSIModulePackage {
|
||||
|
||||
/**
|
||||
* @return a {@link List< JSIModuleSpec >} that contain the list of JSI Modules.
|
||||
*/
|
||||
List<JSIModuleSpec> getJSIModules(ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext);
|
||||
|
||||
/** @return a {@link List< JSIModuleSpec >} that contain the list of JSI Modules. */
|
||||
List<JSIModuleSpec> getJSIModules(
|
||||
ReactApplicationContext reactApplicationContext, JavaScriptContextHolder jsContext);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
public interface JSIModuleProvider<T extends JSIModule> {
|
||||
|
||||
T get();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.infer.annotation.Assertions;
|
||||
@@ -16,7 +15,7 @@ public class JSIModuleRegistry {
|
||||
|
||||
private final Map<JSIModuleType, JSIModuleHolder> mModules = new HashMap<>();
|
||||
|
||||
public JSIModuleRegistry() { }
|
||||
public JSIModuleRegistry() {}
|
||||
|
||||
public JSIModule getModule(JSIModuleType moduleType) {
|
||||
JSIModuleHolder jsiModuleHolder = mModules.get(moduleType);
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* Holder class used to register {@link JSIModule} into JSI Bridge.
|
||||
*/
|
||||
/** Holder class used to register {@link JSIModule} into JSI Bridge. */
|
||||
public interface JSIModuleSpec<T extends JSIModule> {
|
||||
|
||||
JSIModuleType getJSIModuleType();
|
||||
|
||||
JSIModuleProvider<T> getJSIModuleProvider();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* A list of support JSIModules. These are usually core infra pieces, so there
|
||||
* should be an explicit list.
|
||||
* A list of support JSIModules. These are usually core infra pieces, so there should be an explicit
|
||||
* list.
|
||||
*/
|
||||
public enum JSIModuleType {
|
||||
TurboModuleManager,
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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;
|
||||
|
||||
/**
|
||||
* This interface includes the methods needed to use a running JS
|
||||
* instance, without specifying any of the bridge-specific
|
||||
* initialization or lifecycle management.
|
||||
* This interface includes the methods needed to use a running JS instance, without specifying any
|
||||
* of the bridge-specific initialization or lifecycle management.
|
||||
*/
|
||||
public interface JSInstance {
|
||||
void invokeCallback(
|
||||
int callbackID,
|
||||
NativeArrayInterface arguments);
|
||||
void invokeCallback(int callbackID, NativeArrayInterface arguments);
|
||||
// TODO if this interface survives refactoring, think about adding
|
||||
// callFunction.
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 com.facebook.proguard.annotations.DoNotStrip;
|
||||
|
||||
/**
|
||||
* This is class represents java version of native js executor interface. When set through
|
||||
* {@link ProxyJavaScriptExecutor} as a {@link CatalystInstance} executor, native code will
|
||||
* delegate js calls to the given implementation of this interface.
|
||||
* This is class represents java version of native js executor interface. When set through {@link
|
||||
* ProxyJavaScriptExecutor} as a {@link CatalystInstance} executor, native code will delegate js
|
||||
* calls to the given implementation of this interface.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public interface JavaJSExecutor {
|
||||
@@ -27,13 +26,14 @@ public interface JavaJSExecutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this executor and cleanup any resources that it was using. No further calls are
|
||||
* expected after this.
|
||||
* Close this executor and cleanup any resources that it was using. No further calls are expected
|
||||
* after this.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Load javascript into the js context
|
||||
*
|
||||
* @param sourceURL url or file location from which script content was loaded
|
||||
*/
|
||||
@DoNotStrip
|
||||
@@ -41,13 +41,13 @@ public interface JavaJSExecutor {
|
||||
|
||||
/**
|
||||
* Execute javascript method within js context
|
||||
*
|
||||
* @param methodName name of the method to be executed
|
||||
* @param jsonArgsArray json encoded array of arguments provided for the method call
|
||||
* @return json encoded value returned from the method call
|
||||
*/
|
||||
@DoNotStrip
|
||||
String executeJSCall(String methodName, String jsonArgsArray)
|
||||
throws ProxyExecutorException;
|
||||
String executeJSCall(String methodName, String jsonArgsArray) throws ProxyExecutorException;
|
||||
|
||||
@DoNotStrip
|
||||
void setGlobalVariable(String propertyName, String jsonEncodedValue);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 static com.facebook.infer.annotation.Assertions.assertNotNull;
|
||||
@@ -20,118 +19,118 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
|
||||
private static abstract class ArgumentExtractor<T> {
|
||||
private abstract static class ArgumentExtractor<T> {
|
||||
public int getJSArgumentsNeeded() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public abstract @Nullable T extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex);
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex);
|
||||
}
|
||||
|
||||
static final private ArgumentExtractor<Boolean> ARGUMENT_EXTRACTOR_BOOLEAN =
|
||||
new ArgumentExtractor<Boolean>() {
|
||||
@Override
|
||||
public Boolean extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getBoolean(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Double> ARGUMENT_EXTRACTOR_DOUBLE =
|
||||
new ArgumentExtractor<Double>() {
|
||||
@Override
|
||||
public Double extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Float> ARGUMENT_EXTRACTOR_FLOAT =
|
||||
new ArgumentExtractor<Float>() {
|
||||
@Override
|
||||
public Float extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return (float) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Integer> ARGUMENT_EXTRACTOR_INTEGER =
|
||||
new ArgumentExtractor<Integer>() {
|
||||
@Override
|
||||
public Integer extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return (int) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<String> ARGUMENT_EXTRACTOR_STRING =
|
||||
new ArgumentExtractor<String>() {
|
||||
@Override
|
||||
public String extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getString(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<ReadableArray> ARGUMENT_EXTRACTOR_ARRAY =
|
||||
new ArgumentExtractor<ReadableArray>() {
|
||||
@Override
|
||||
public ReadableArray extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getArray(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Dynamic> ARGUMENT_EXTRACTOR_DYNAMIC =
|
||||
new ArgumentExtractor<Dynamic>() {
|
||||
@Override
|
||||
public Dynamic extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return DynamicFromArray.create(jsArguments, atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<ReadableMap> ARGUMENT_EXTRACTOR_MAP =
|
||||
new ArgumentExtractor<ReadableMap>() {
|
||||
@Override
|
||||
public ReadableMap extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getMap(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Callback> ARGUMENT_EXTRACTOR_CALLBACK =
|
||||
new ArgumentExtractor<Callback>() {
|
||||
@Override
|
||||
public @Nullable Callback extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
if (jsArguments.isNull(atIndex)) {
|
||||
return null;
|
||||
} else {
|
||||
int id = (int) jsArguments.getDouble(atIndex);
|
||||
return new com.facebook.react.bridge.CallbackImpl(jsInstance, id);
|
||||
private static final ArgumentExtractor<Boolean> ARGUMENT_EXTRACTOR_BOOLEAN =
|
||||
new ArgumentExtractor<Boolean>() {
|
||||
@Override
|
||||
public Boolean extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getBoolean(atIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static final private ArgumentExtractor<Promise> ARGUMENT_EXTRACTOR_PROMISE =
|
||||
new ArgumentExtractor<Promise>() {
|
||||
@Override
|
||||
public int getJSArgumentsNeeded() {
|
||||
return 2;
|
||||
}
|
||||
private static final ArgumentExtractor<Double> ARGUMENT_EXTRACTOR_DOUBLE =
|
||||
new ArgumentExtractor<Double>() {
|
||||
@Override
|
||||
public Double extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Promise extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
Callback resolve = ARGUMENT_EXTRACTOR_CALLBACK
|
||||
.extractArgument(jsInstance, jsArguments, atIndex);
|
||||
Callback reject = ARGUMENT_EXTRACTOR_CALLBACK
|
||||
.extractArgument(jsInstance, jsArguments, atIndex + 1);
|
||||
return new PromiseImpl(resolve, reject);
|
||||
}
|
||||
};
|
||||
private static final ArgumentExtractor<Float> ARGUMENT_EXTRACTOR_FLOAT =
|
||||
new ArgumentExtractor<Float>() {
|
||||
@Override
|
||||
public Float extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return (float) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<Integer> ARGUMENT_EXTRACTOR_INTEGER =
|
||||
new ArgumentExtractor<Integer>() {
|
||||
@Override
|
||||
public Integer extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return (int) jsArguments.getDouble(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<String> ARGUMENT_EXTRACTOR_STRING =
|
||||
new ArgumentExtractor<String>() {
|
||||
@Override
|
||||
public String extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getString(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<ReadableArray> ARGUMENT_EXTRACTOR_ARRAY =
|
||||
new ArgumentExtractor<ReadableArray>() {
|
||||
@Override
|
||||
public ReadableArray extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getArray(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<Dynamic> ARGUMENT_EXTRACTOR_DYNAMIC =
|
||||
new ArgumentExtractor<Dynamic>() {
|
||||
@Override
|
||||
public Dynamic extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return DynamicFromArray.create(jsArguments, atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<ReadableMap> ARGUMENT_EXTRACTOR_MAP =
|
||||
new ArgumentExtractor<ReadableMap>() {
|
||||
@Override
|
||||
public ReadableMap extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
return jsArguments.getMap(atIndex);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<Callback> ARGUMENT_EXTRACTOR_CALLBACK =
|
||||
new ArgumentExtractor<Callback>() {
|
||||
@Override
|
||||
public @Nullable Callback extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
if (jsArguments.isNull(atIndex)) {
|
||||
return null;
|
||||
} else {
|
||||
int id = (int) jsArguments.getDouble(atIndex);
|
||||
return new com.facebook.react.bridge.CallbackImpl(jsInstance, id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final ArgumentExtractor<Promise> ARGUMENT_EXTRACTOR_PROMISE =
|
||||
new ArgumentExtractor<Promise>() {
|
||||
@Override
|
||||
public int getJSArgumentsNeeded() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Promise extractArgument(
|
||||
JSInstance jsInstance, ReadableArray jsArguments, int atIndex) {
|
||||
Callback resolve =
|
||||
ARGUMENT_EXTRACTOR_CALLBACK.extractArgument(jsInstance, jsArguments, atIndex);
|
||||
Callback reject =
|
||||
ARGUMENT_EXTRACTOR_CALLBACK.extractArgument(jsInstance, jsArguments, atIndex + 1);
|
||||
return new PromiseImpl(resolve, reject);
|
||||
}
|
||||
};
|
||||
|
||||
private static final boolean DEBUG =
|
||||
PrinterHolder.getPrinter().shouldDisplayLogMessage(ReactDebugOverlayTags.BRIDGE_CALLS);
|
||||
@@ -152,8 +151,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
} else if (paramClass == Dynamic.class) {
|
||||
return 'Y';
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Got unknown param class: " + paramClass.getSimpleName());
|
||||
throw new RuntimeException("Got unknown param class: " + paramClass.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +168,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
} else if (returnClass == WritableArray.class) {
|
||||
return 'A';
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Got unknown return class: " + returnClass.getSimpleName());
|
||||
throw new RuntimeException("Got unknown return class: " + returnClass.getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,15 +226,13 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
return;
|
||||
}
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processArguments")
|
||||
.arg("method", mModuleWrapper.getName() + "." + mMethod.getName())
|
||||
.flush();
|
||||
.arg("method", mModuleWrapper.getName() + "." + mMethod.getName())
|
||||
.flush();
|
||||
try {
|
||||
mArgumentsProcessed = true;
|
||||
mArgumentExtractors = buildArgumentExtractors(mParameterTypes);
|
||||
mSignature = buildSignature(
|
||||
mMethod,
|
||||
mParameterTypes,
|
||||
(mType.equals(BaseJavaModule.METHOD_TYPE_SYNC)));
|
||||
mSignature =
|
||||
buildSignature(mMethod, mParameterTypes, (mType.equals(BaseJavaModule.METHOD_TYPE_SYNC)));
|
||||
// Since native methods are invoked from a message queue executed on a single thread, it is
|
||||
// safe to allocate only one arguments object per method that can be reused across calls
|
||||
mArguments = new Object[mParameterTypes.length];
|
||||
@@ -272,7 +267,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
Class paramClass = paramTypes[i];
|
||||
if (paramClass == Promise.class) {
|
||||
Assertions.assertCondition(
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
}
|
||||
builder.append(paramTypeToChar(paramClass));
|
||||
}
|
||||
@@ -299,7 +294,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
} else if (argumentClass == Promise.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_PROMISE;
|
||||
Assertions.assertCondition(
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
i == paramTypes.length - 1, "Promise must be used as last parameter only");
|
||||
} else if (argumentClass == ReadableMap.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_MAP;
|
||||
} else if (argumentClass == ReadableArray.class) {
|
||||
@@ -307,8 +302,7 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
} else if (argumentClass == Dynamic.class) {
|
||||
argumentExtractors[i] = ARGUMENT_EXTRACTOR_DYNAMIC;
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"Got unknown argument class: " + argumentClass.getSimpleName());
|
||||
throw new RuntimeException("Got unknown argument class: " + argumentClass.getSimpleName());
|
||||
}
|
||||
}
|
||||
return argumentExtractors;
|
||||
@@ -323,16 +317,17 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
}
|
||||
|
||||
private String getAffectedRange(int startIndex, int jsArgumentsNeeded) {
|
||||
return jsArgumentsNeeded > 1 ?
|
||||
"" + startIndex + "-" + (startIndex + jsArgumentsNeeded - 1) : "" + startIndex;
|
||||
return jsArgumentsNeeded > 1
|
||||
? "" + startIndex + "-" + (startIndex + jsArgumentsNeeded - 1)
|
||||
: "" + startIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(JSInstance jsInstance, ReadableArray parameters) {
|
||||
String traceName = mModuleWrapper.getName() + "." + mMethod.getName();
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "callJavaModuleMethod")
|
||||
.arg("method", traceName)
|
||||
.flush();
|
||||
.arg("method", traceName)
|
||||
.flush();
|
||||
if (DEBUG) {
|
||||
PrinterHolder.getPrinter()
|
||||
.logMessage(
|
||||
@@ -350,22 +345,26 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
}
|
||||
if (mJSArgumentsNeeded != parameters.size()) {
|
||||
throw new NativeArgumentsParseException(
|
||||
traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
|
||||
traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded);
|
||||
}
|
||||
|
||||
int i = 0, jsArgumentsConsumed = 0;
|
||||
try {
|
||||
for (; i < mArgumentExtractors.length; i++) {
|
||||
mArguments[i] = mArgumentExtractors[i].extractArgument(
|
||||
jsInstance, parameters, jsArgumentsConsumed);
|
||||
mArguments[i] =
|
||||
mArgumentExtractors[i].extractArgument(jsInstance, parameters, jsArgumentsConsumed);
|
||||
jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded();
|
||||
}
|
||||
} catch (UnexpectedNativeTypeException e) {
|
||||
throw new NativeArgumentsParseException(
|
||||
e.getMessage() + " (constructing arguments for " + traceName + " at argument index " +
|
||||
getAffectedRange(jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded()) +
|
||||
")",
|
||||
e);
|
||||
e.getMessage()
|
||||
+ " (constructing arguments for "
|
||||
+ traceName
|
||||
+ " at argument index "
|
||||
+ getAffectedRange(
|
||||
jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded())
|
||||
+ ")",
|
||||
e);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -388,10 +387,9 @@ public class JavaMethodWrapper implements NativeModule.NativeMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines how the method is exported in JavaScript:
|
||||
* METHOD_TYPE_ASYNC for regular methods
|
||||
* METHOD_TYPE_PROMISE for methods that return a promise object to the caller.
|
||||
* METHOD_TYPE_SYNC for sync methods
|
||||
* Determines how the method is exported in JavaScript: METHOD_TYPE_ASYNC for regular methods
|
||||
* METHOD_TYPE_PROMISE for methods that return a promise object to the caller. METHOD_TYPE_SYNC
|
||||
* for sync methods
|
||||
*/
|
||||
@Override
|
||||
public String getType() {
|
||||
|
||||
@@ -1,50 +1,41 @@
|
||||
/**
|
||||
* 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.
|
||||
* <p>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 javax.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CONVERT_CONSTANTS_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.CONVERT_CONSTANTS_START;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.GET_CONSTANTS_END;
|
||||
import static com.facebook.react.bridge.ReactMarkerConstants.GET_CONSTANTS_START;
|
||||
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
|
||||
|
||||
/**
|
||||
* This is part of the glue which wraps a java BaseJavaModule in a C++
|
||||
* NativeModule. This could all be in C++, but it's android-specific
|
||||
* initialization code, and writing it this way is easier to read and means
|
||||
* fewer JNI calls.
|
||||
*/
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import com.facebook.systrace.SystraceMessage;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This is part of the glue which wraps a java BaseJavaModule in a C++ NativeModule. This could all
|
||||
* be in C++, but it's android-specific initialization code, and writing it this way is easier to
|
||||
* read and means fewer JNI calls.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class JavaModuleWrapper {
|
||||
@DoNotStrip
|
||||
public class MethodDescriptor {
|
||||
@DoNotStrip
|
||||
Method method;
|
||||
@DoNotStrip
|
||||
String signature;
|
||||
@DoNotStrip
|
||||
String name;
|
||||
@DoNotStrip
|
||||
String type;
|
||||
@DoNotStrip Method method;
|
||||
@DoNotStrip String signature;
|
||||
@DoNotStrip String name;
|
||||
@DoNotStrip String type;
|
||||
}
|
||||
|
||||
private final JSInstance mJSInstance;
|
||||
@@ -93,10 +84,11 @@ public class JavaModuleWrapper {
|
||||
// We do not support method overloading since js sees a function as an object regardless
|
||||
// of number of params.
|
||||
throw new IllegalArgumentException(
|
||||
"Java Module " + getName() + " method name already registered: " + methodName);
|
||||
"Java Module " + getName() + " method name already registered: " + methodName);
|
||||
}
|
||||
MethodDescriptor md = new MethodDescriptor();
|
||||
JavaMethodWrapper method = new JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod());
|
||||
JavaMethodWrapper method =
|
||||
new JavaMethodWrapper(this, targetMethod, annotation.isBlockingSynchronousMethod());
|
||||
md.name = methodName;
|
||||
md.type = method.getType();
|
||||
if (md.type == BaseJavaModule.METHOD_TYPE_SYNC) {
|
||||
@@ -126,8 +118,8 @@ public class JavaModuleWrapper {
|
||||
|
||||
final String moduleName = getName();
|
||||
SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "JavaModuleWrapper.getConstants")
|
||||
.arg("moduleName", moduleName)
|
||||
.flush();
|
||||
.arg("moduleName", moduleName)
|
||||
.flush();
|
||||
ReactMarker.logMarker(GET_CONSTANTS_START, moduleName);
|
||||
|
||||
BaseJavaModule baseJavaModule = getModule();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user