mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Migrate AnimatedNode.java to Kotlin (#45601)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45601 AnimatedNode.java -> AnimatedNode.kt changelog: [internal] internal Reviewed By: tdn120 Differential Revision: D60076481 fbshipit-source-id: a969b05e9e339457526a454c13a9584363772d85
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7dec080545
commit
377352d956
@@ -439,6 +439,23 @@ public abstract interface class com/facebook/react/ViewManagerOnDemandReactPacka
|
||||
public abstract fun getViewManagerNames (Lcom/facebook/react/bridge/ReactApplicationContext;)Ljava/util/Collection;
|
||||
}
|
||||
|
||||
public abstract class com/facebook/react/animated/AnimatedNode {
|
||||
public static final field Companion Lcom/facebook/react/animated/AnimatedNode$Companion;
|
||||
public static final field DEFAULT_ANIMATED_NODE_CHILD_COUNT I
|
||||
public static final field INITIAL_BFS_COLOR I
|
||||
public fun <init> ()V
|
||||
public final fun addChild (Lcom/facebook/react/animated/AnimatedNode;)V
|
||||
public fun onAttachedToNode (Lcom/facebook/react/animated/AnimatedNode;)V
|
||||
public fun onDetachedFromNode (Lcom/facebook/react/animated/AnimatedNode;)V
|
||||
public abstract fun prettyPrint ()Ljava/lang/String;
|
||||
public final fun prettyPrintWithChildren ()Ljava/lang/String;
|
||||
public final fun removeChild (Lcom/facebook/react/animated/AnimatedNode;)V
|
||||
public fun update ()V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/animated/AnimatedNode$Companion {
|
||||
}
|
||||
|
||||
public class com/facebook/react/animated/NativeAnimatedModule : com/facebook/fbreact/specs/NativeAnimatedModuleSpec, com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/bridge/UIManagerListener {
|
||||
public static final field ANIMATED_MODULE_DEBUG Z
|
||||
public fun <init> (Lcom/facebook/react/bridge/ReactApplicationContext;)V
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "AdditionAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: input nodes: "
|
||||
+ (mInputNodes != null ? mInputNodes.toString() : "null")
|
||||
+ " - super: "
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.animated;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Base class for all Animated.js library node types that can be created on the "native" side. */
|
||||
/*package*/ @Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
abstract class AnimatedNode {
|
||||
|
||||
public static final int INITIAL_BFS_COLOR = 0;
|
||||
|
||||
private static final int DEFAULT_ANIMATED_NODE_CHILD_COUNT = 1;
|
||||
|
||||
/*package*/ @Nullable List<AnimatedNode> mChildren; /* lazy-initialized when a child is added */
|
||||
/*package*/ int mActiveIncomingNodes = 0;
|
||||
/*package*/ int mBFSColor = INITIAL_BFS_COLOR;
|
||||
/*package*/ int mTag = -1;
|
||||
|
||||
public final void addChild(AnimatedNode child) {
|
||||
if (mChildren == null) {
|
||||
mChildren = new ArrayList<>(DEFAULT_ANIMATED_NODE_CHILD_COUNT);
|
||||
}
|
||||
Assertions.assertNotNull(mChildren).add(child);
|
||||
child.onAttachedToNode(this);
|
||||
}
|
||||
|
||||
public final void removeChild(AnimatedNode child) {
|
||||
if (mChildren == null) {
|
||||
return;
|
||||
}
|
||||
child.onDetachedFromNode(this);
|
||||
mChildren.remove(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void onAttachedToNode(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() {}
|
||||
|
||||
/**
|
||||
* Pretty-printer for the AnimatedNode. Only called in production pre-crash for debug diagnostics.
|
||||
*/
|
||||
public abstract String prettyPrint();
|
||||
|
||||
public String prettyPrintWithChildren() {
|
||||
String children = "";
|
||||
if (mChildren != null && mChildren.size() > 0) {
|
||||
for (AnimatedNode child : mChildren) {
|
||||
children += " " + child.mTag;
|
||||
}
|
||||
}
|
||||
|
||||
return prettyPrint() + (children.length() > 0 ? " children: " + children : "");
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.animated
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
/** Base class for all Animated.js library node types that can be created on the "native" side. */
|
||||
public abstract class AnimatedNode {
|
||||
|
||||
public companion object {
|
||||
public const val INITIAL_BFS_COLOR: Int = 0
|
||||
public const val DEFAULT_ANIMATED_NODE_CHILD_COUNT: Int = 1
|
||||
}
|
||||
|
||||
// TODO: T196787278 Reduce the visibility of these fields to package once we have
|
||||
// converted the whole module to Kotlin
|
||||
|
||||
@JvmField
|
||||
internal var children: MutableList<AnimatedNode>? =
|
||||
null /* lazy-initialized when a child is added */
|
||||
@JvmField internal var activeIncomingNodes: Int = 0
|
||||
@JvmField internal var BFSColor: Int = INITIAL_BFS_COLOR
|
||||
@JvmField internal var tag: Int = -1
|
||||
|
||||
public fun addChild(child: AnimatedNode): Unit {
|
||||
val currentChildren =
|
||||
children
|
||||
?: ArrayList<AnimatedNode>(DEFAULT_ANIMATED_NODE_CHILD_COUNT).also { children = it }
|
||||
|
||||
currentChildren.add(child)
|
||||
child.onAttachedToNode(this)
|
||||
}
|
||||
|
||||
public fun removeChild(child: AnimatedNode): Unit {
|
||||
val currentChildren = children ?: return
|
||||
child.onDetachedFromNode(this)
|
||||
currentChildren.remove(child)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public open fun onAttachedToNode(parent: AnimatedNode): Unit = Unit
|
||||
|
||||
/** See {@link #onAttachedToNode} */
|
||||
public open fun onDetachedFromNode(parent: AnimatedNode): Unit = Unit
|
||||
|
||||
/**
|
||||
* 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 open fun update(): Unit = Unit
|
||||
|
||||
/**
|
||||
* Pretty-printer for the AnimatedNode. Only called in production pre-crash for debug diagnostics.
|
||||
*/
|
||||
public abstract fun prettyPrint(): String
|
||||
|
||||
public fun prettyPrintWithChildren(): String {
|
||||
|
||||
val currentChildren = children?.joinToString(" ")
|
||||
return prettyPrint() +
|
||||
if (!currentChildren.isNullOrBlank()) " children: $currentChildren" else ""
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -66,7 +66,7 @@ import com.facebook.react.views.view.ColorUtil;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "ColorAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: r: "
|
||||
+ mRNodeId
|
||||
+ " g: "
|
||||
@@ -116,8 +116,8 @@ import com.facebook.react.views.view.ColorUtil;
|
||||
private static Context getContextHelper(AnimatedNode node) {
|
||||
// Search children depth-first until we get to a PropsAnimatedNode, from which we can
|
||||
// get the view and its context
|
||||
if (node.mChildren != null) {
|
||||
for (AnimatedNode child : node.mChildren) {
|
||||
if (node.children != null) {
|
||||
for (AnimatedNode child : node.children) {
|
||||
if (child instanceof PropsAnimatedNode) {
|
||||
View view = ((PropsAnimatedNode) child).getConnectedView();
|
||||
return view != null ? view.getContext() : null;
|
||||
|
||||
+1
-1
@@ -46,6 +46,6 @@ internal class DiffClampAnimatedNode(
|
||||
}
|
||||
|
||||
override fun prettyPrint(): String =
|
||||
"DiffClampAnimatedNode[$mTag]: InputNodeTag: $inputNodeTag min: $minValue " +
|
||||
"DiffClampAnimatedNode[$tag]: InputNodeTag: $inputNodeTag min: $minValue " +
|
||||
"max: $maxValue lastValue: $lastValue super: ${super.prettyPrint()}"
|
||||
}
|
||||
|
||||
+3
-3
@@ -42,12 +42,12 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
}
|
||||
if (value == 0) {
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Detected a division by zero in Animated.divide node with Animated ID " + mTag);
|
||||
"Detected a division by zero in Animated.divide node with Animated ID " + tag);
|
||||
}
|
||||
mValue /= value;
|
||||
} else {
|
||||
throw new JSApplicationCausedNativeException(
|
||||
"Illegal node ID set as an input for Animated.divide node with Animated ID " + mTag);
|
||||
"Illegal node ID set as an input for Animated.divide node with Animated ID " + tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "DivisionAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: input nodes: "
|
||||
+ (mInputNodes != null ? mInputNodes.toString() : "null")
|
||||
+ " - super: "
|
||||
|
||||
+1
-1
@@ -306,6 +306,6 @@ import java.util.regex.Pattern;
|
||||
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "InterpolationAnimatedNode[" + mTag + "] super: " + super.prettyPrint();
|
||||
return "InterpolationAnimatedNode[" + tag + "] super: " + super.prettyPrint();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,6 +30,6 @@ internal class ModulusAnimatedNode(
|
||||
}
|
||||
|
||||
override public fun prettyPrint(): String {
|
||||
return "NativeAnimatedNodesManager[$mTag] inputNode: $inputNode modulus: $modulus super: ${super.prettyPrint()}"
|
||||
return "NativeAnimatedNodesManager[$tag] inputNode: $inputNode modulus: $modulus super: ${super.prettyPrint()}"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "MultiplicationAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: input nodes: "
|
||||
+ (mInputNodes != null ? mInputNodes.toString() : "null")
|
||||
+ " - super: "
|
||||
|
||||
+25
-25
@@ -149,7 +149,7 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
} else {
|
||||
throw new JSApplicationIllegalArgumentException("Unsupported node type: " + type);
|
||||
}
|
||||
node.mTag = tag;
|
||||
node.tag = tag;
|
||||
mAnimatedNodes.put(tag, node);
|
||||
mUpdatedNodes.put(tag, node);
|
||||
}
|
||||
@@ -565,7 +565,7 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
EventAnimationDriver driver = it.next();
|
||||
if (eventName.equals(driver.mEventName)
|
||||
&& viewTag == driver.mViewTag
|
||||
&& animatedValueTag == driver.mValueNode.mTag) {
|
||||
&& animatedValueTag == driver.mValueNode.tag) {
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
@@ -632,7 +632,7 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
* <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
|
||||
* an attribute {@code activeIncomingNodes}. 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
|
||||
* "predecessors" have already been visited.
|
||||
*/
|
||||
@@ -706,9 +706,9 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
if (driver != null) {
|
||||
if (eventName.equals(driver.mEventName) && tag == driver.mViewTag) {
|
||||
tags.add(driver.mViewTag);
|
||||
if (driver.mValueNode != null && driver.mValueNode.mChildren != null) {
|
||||
for (AnimatedNode node : driver.mValueNode.mChildren) {
|
||||
tags.add(node.mTag);
|
||||
if (driver.mValueNode != null && driver.mValueNode.children != null) {
|
||||
for (AnimatedNode node : driver.mValueNode.children) {
|
||||
tags.add(node.tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -737,8 +737,8 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
|
||||
Queue<AnimatedNode> nodesQueue = new ArrayDeque<>();
|
||||
for (AnimatedNode node : nodes) {
|
||||
if (node.mBFSColor != mAnimatedGraphBFSColor) {
|
||||
node.mBFSColor = mAnimatedGraphBFSColor;
|
||||
if (node.BFSColor != mAnimatedGraphBFSColor) {
|
||||
node.BFSColor = mAnimatedGraphBFSColor;
|
||||
activeNodesCount++;
|
||||
nodesQueue.add(node);
|
||||
}
|
||||
@@ -746,12 +746,12 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
|
||||
while (!nodesQueue.isEmpty()) {
|
||||
AnimatedNode nextNode = nodesQueue.poll();
|
||||
if (nextNode.mChildren != null) {
|
||||
for (int i = 0; i < nextNode.mChildren.size(); i++) {
|
||||
AnimatedNode child = nextNode.mChildren.get(i);
|
||||
child.mActiveIncomingNodes++;
|
||||
if (child.mBFSColor != mAnimatedGraphBFSColor) {
|
||||
child.mBFSColor = mAnimatedGraphBFSColor;
|
||||
if (nextNode.children != null) {
|
||||
for (int i = 0; i < nextNode.children.size(); i++) {
|
||||
AnimatedNode child = nextNode.children.get(i);
|
||||
child.activeIncomingNodes++;
|
||||
if (child.BFSColor != mAnimatedGraphBFSColor) {
|
||||
child.BFSColor = mAnimatedGraphBFSColor;
|
||||
activeNodesCount++;
|
||||
nodesQueue.add(child);
|
||||
}
|
||||
@@ -764,7 +764,7 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
// "predecessors" in the graph have already been visited. It is important to visit nodes in that
|
||||
// order as they may often use values of their predecessors in order to calculate "next state"
|
||||
// of their own. We start by determining the starting set of nodes by looking for nodes with
|
||||
// `mActiveIncomingNodes = 0` (those can only be the ones that we start BFS in the previous
|
||||
// `activeIncomingNodes = 0` (those can only be the ones that we start BFS in the previous
|
||||
// step). We store number of visited nodes in this step in `updatedNodesCount`
|
||||
|
||||
mAnimatedGraphBFSColor++;
|
||||
@@ -776,8 +776,8 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
// find nodes with zero "incoming nodes", those can be either nodes from `mUpdatedNodes` or
|
||||
// ones connected to active animations
|
||||
for (AnimatedNode node : nodes) {
|
||||
if (node.mActiveIncomingNodes == 0 && node.mBFSColor != mAnimatedGraphBFSColor) {
|
||||
node.mBFSColor = mAnimatedGraphBFSColor;
|
||||
if (node.activeIncomingNodes == 0 && node.BFSColor != mAnimatedGraphBFSColor) {
|
||||
node.BFSColor = mAnimatedGraphBFSColor;
|
||||
updatedNodesCount++;
|
||||
nodesQueue.add(node);
|
||||
}
|
||||
@@ -807,15 +807,15 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
// Potentially send events to JS when the node's value is updated
|
||||
((ValueAnimatedNode) nextNode).onValueUpdate();
|
||||
}
|
||||
if (nextNode.mChildren != null) {
|
||||
for (int i = 0; i < nextNode.mChildren.size(); i++) {
|
||||
AnimatedNode child = nextNode.mChildren.get(i);
|
||||
child.mActiveIncomingNodes--;
|
||||
if (child.mBFSColor != mAnimatedGraphBFSColor && child.mActiveIncomingNodes == 0) {
|
||||
child.mBFSColor = mAnimatedGraphBFSColor;
|
||||
if (nextNode.children != null) {
|
||||
for (int i = 0; i < nextNode.children.size(); i++) {
|
||||
AnimatedNode child = nextNode.children.get(i);
|
||||
child.activeIncomingNodes--;
|
||||
if (child.BFSColor != mAnimatedGraphBFSColor && child.activeIncomingNodes == 0) {
|
||||
child.BFSColor = mAnimatedGraphBFSColor;
|
||||
updatedNodesCount++;
|
||||
nodesQueue.add(child);
|
||||
} else if (child.mBFSColor == mAnimatedGraphBFSColor) {
|
||||
} else if (child.BFSColor == mAnimatedGraphBFSColor) {
|
||||
cyclesDetected++;
|
||||
}
|
||||
}
|
||||
@@ -825,7 +825,7 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
|
||||
// Verify that we've visited *all* active nodes. Throw otherwise as this could mean there is a
|
||||
// cycle in animated node graph, or that the graph is only partially set up. We also take
|
||||
// advantage of the fact that all active nodes are visited in the step above so that all the
|
||||
// nodes properties `mActiveIncomingNodes` are set to zero.
|
||||
// nodes properties `activeIncomingNodes` are set to zero.
|
||||
// In Fabric there can be race conditions between the JS thread setting up or tearing down
|
||||
// animated nodes, and Fabric executing them on the UI thread, leading to temporary inconsistent
|
||||
// states.
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ class ObjectAnimatedNode extends AnimatedNode {
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "ObjectAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: mConfig: "
|
||||
+ (mConfig != null ? mConfig.toString() : "null");
|
||||
}
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ import java.util.Map;
|
||||
public void connectToView(int viewTag, UIManager uiManager) {
|
||||
if (mConnectedViewTag != -1) {
|
||||
throw new JSApplicationIllegalArgumentException(
|
||||
"Animated node " + mTag + " is " + "already attached to a view: " + mConnectedViewTag);
|
||||
"Animated node " + tag + " is " + "already attached to a view: " + mConnectedViewTag);
|
||||
}
|
||||
mConnectedViewTag = viewTag;
|
||||
mUIManager = uiManager;
|
||||
@@ -134,7 +134,7 @@ import java.util.Map;
|
||||
|
||||
public String prettyPrint() {
|
||||
return "PropsAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "] connectedViewTag: "
|
||||
+ mConnectedViewTag
|
||||
+ " mPropNodeMapping: "
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ import java.util.Map;
|
||||
|
||||
public String prettyPrint() {
|
||||
return "StyleAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "] mPropMapping: "
|
||||
+ (mPropMapping != null ? mPropMapping.toString() : "null");
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "SubtractionAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: input nodes: "
|
||||
+ (mInputNodes != null ? mInputNodes.toString() : "null")
|
||||
+ " - super: "
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "TrackingAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: animationID: "
|
||||
+ mAnimationId
|
||||
+ " toValueNode: "
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ import java.util.List;
|
||||
@Override
|
||||
public String prettyPrint() {
|
||||
return "TransformAnimatedNode["
|
||||
+ mTag
|
||||
+ tag
|
||||
+ "]: mTransformConfigs: "
|
||||
+ (mTransformConfigs != null ? mTransformConfigs.toString() : "null");
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,6 +61,6 @@ import com.facebook.react.bridge.ReadableMap;
|
||||
}
|
||||
|
||||
public String prettyPrint() {
|
||||
return "ValueAnimatedNode[" + mTag + "]: value: " + mValue + " offset: " + mOffset;
|
||||
return "ValueAnimatedNode[" + tag + "]: value: " + mValue + " offset: " + mOffset;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user